Hello community, here is the log from the commit of package bumblebee-status for openSUSE:Factory checked in at 2018-01-26 13:40:26 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/bumblebee-status (Old) and /work/SRC/openSUSE:Factory/.bumblebee-status.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "bumblebee-status" Fri Jan 26 13:40:26 2018 rev:4 rq:569758 version:1.6.0 Changes: -------- --- /work/SRC/openSUSE:Factory/bumblebee-status/bumblebee-status.changes 2018-01-16 09:42:54.352185722 +0100 +++ /work/SRC/openSUSE:Factory/.bumblebee-status.new/bumblebee-status.changes 2018-01-26 13:40:32.174389701 +0100 @@ -1,0 +2,12 @@ +Fri Jan 19 05:34:23 UTC 2018 - avindra@opensuse.org + +- Update to 1.6.0 + * redshift module now updates in the background and no longer + blocks the bar + * Awesome fonts in the theme can now be referenced by name + (using ${}) + * Add generic mechanism for slow updates, and apply it to + various modules + * Update stock widget only every hour + +------------------------------------------------------------------- Old: ---- bumblebee-status-1.5.1.tar.gz New: ---- bumblebee-status-1.6.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ bumblebee-status.spec ++++++ --- /var/tmp/diff_new_pack.TeQa4t/_old 2018-01-26 13:40:33.438330671 +0100 +++ /var/tmp/diff_new_pack.TeQa4t/_new 2018-01-26 13:40:33.438330671 +0100 @@ -17,7 +17,7 @@ Name: bumblebee-status -Version: 1.5.1 +Version: 1.6.0 Release: 0 Summary: Modular, theme-able status line generator for the i3 window manager License: MIT ++++++ bumblebee-status-1.5.1.tar.gz -> bumblebee-status-1.6.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumblebee-status-1.5.1/.travis.yml new/bumblebee-status-1.6.0/.travis.yml --- old/bumblebee-status-1.5.1/.travis.yml 2017-12-19 18:29:39.000000000 +0100 +++ new/bumblebee-status-1.6.0/.travis.yml 2018-01-07 20:41:14.000000000 +0100 @@ -10,6 +10,7 @@ - pip install i3ipc - pip install psutil - pip install netifaces + - pip install pyyaml - pip install -U coverage==4.3 - pip install codeclimate-test-reporter script: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumblebee-status-1.5.1/README.md new/bumblebee-status-1.6.0/README.md --- old/bumblebee-status-1.5.1/README.md 2017-12-19 18:29:39.000000000 +0100 +++ new/bumblebee-status-1.6.0/README.md 2018-01-07 20:41:14.000000000 +0100 @@ -142,7 +142,7 @@ * requests (for the modules 'weather', 'github', 'getcrypto', 'stock') * power (for the module 'battery') * dbus (for the module 'spotify') -* i3rpc (for the module 'title') +* i3ipc (for the module 'title') # Required commandline utilities diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumblebee-status-1.5.1/bumblebee/engine.py new/bumblebee-status-1.6.0/bumblebee/engine.py --- old/bumblebee-status-1.5.1/bumblebee/engine.py 2017-12-19 18:29:39.000000000 +0100 +++ new/bumblebee-status-1.6.0/bumblebee/engine.py 2018-01-07 20:41:14.000000000 +0100 @@ -2,6 +2,7 @@ import os import json +import time import pkgutil import logging import importlib @@ -37,6 +38,8 @@ self.name = config.get("name", self.__module__.split(".")[-1]) self._config = config self.id = self.name + self._next = int(time.time()) + self._default_interval = 0 self._configFile = None for cfg in [os.path.expanduser("~/.bumblebee-status.conf"), os.path.expanduser("~/.config/bumblebee-status.conf")]: @@ -74,8 +77,18 @@ """By default, update() is a NOP""" pass - def update_all(self): + def update_wrapper(self, widgets): + if self._next > int(time.time()): + return self.update(self._widgets) + self._next += int(self.parameter("interval", self._default_interval))*60 + + def interval(self, intvl): + self._default_interval = intvl + self._next = int(time.time()) + + def update_all(self): + self.update_wrapper(self._widgets) def has_parameter(self, name): v = self.parameter(name) @@ -230,7 +243,7 @@ self._output.begin() for module in self._modules: self._current_module = module - module.update(module.widgets()) + module.update_wrapper(module.widgets()) for widget in module.widgets(): widget.link_module(module) self._output.draw(widget=widget, module=module, engine=self) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumblebee-status-1.5.1/bumblebee/modules/currency.py new/bumblebee-status-1.6.0/bumblebee/modules/currency.py --- old/bumblebee-status-1.5.1/bumblebee/modules/currency.py 2017-12-19 18:29:39.000000000 +0100 +++ new/bumblebee-status-1.6.0/bumblebee/modules/currency.py 2018-01-07 20:41:14.000000000 +0100 @@ -20,7 +20,6 @@ import bumblebee.input import bumblebee.output import bumblebee.engine -import time try: import requests except ImportError: @@ -38,7 +37,7 @@ bumblebee.output.Widget(full_text=self.price) ) self._data = [] - self._interval = int(self.parameter("interval", 1)) + self.interval(1) self._base = self.parameter("source", "GBP") self._symbols = self.parameter("destination", "USD,EUR").split(",") self._nextcheck = 0 @@ -57,16 +56,13 @@ return basefmt.format(SYMBOL[self._base] if self._base in SYMBOL else self._base, ratefmt.join(rates)) def update(self, widgets): - timestamp = int(time.time()) - if self._nextcheck < timestamp: - self._data = [] - self._nextcheck = timestamp + self._interval*60 - for symbol in self._symbols: - url = API_URL.format(self._base, symbol) - try: - response = requests.get(url).json() - self._data.append((symbol, response['data']['exchangeRate'])) - except Exception: - pass + self._data = [] + for symbol in self._symbols: + url = API_URL.format(self._base, symbol) + try: + response = requests.get(url).json() + self._data.append((symbol, response['data']['exchangeRate'])) + except Exception: + pass # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumblebee-status-1.5.1/bumblebee/modules/dnf.py new/bumblebee-status-1.6.0/bumblebee/modules/dnf.py --- old/bumblebee-status-1.5.1/bumblebee/modules/dnf.py 2017-12-19 18:29:39.000000000 +0100 +++ new/bumblebee-status-1.6.0/bumblebee/modules/dnf.py 2018-01-07 20:41:14.000000000 +0100 @@ -6,11 +6,10 @@ * dnf Parameters: - * dnf.interval: Time in seconds between two consecutive update checks (defaulst to 1800) + * dnf.interval: Time in seconds between two consecutive update checks (defaulst to 30 minutes) """ -import time import threading import bumblebee.util @@ -53,7 +52,7 @@ def __init__(self, engine, config): widget = bumblebee.output.Widget(full_text=self.updates) super(Module, self).__init__(engine, config, widget) - self._next_check = 0 + self.interval(30) def updates(self, widget): result = [] @@ -62,11 +61,8 @@ return "/".join(result) def update(self, widgets): - if int(time.time()) < self._next_check: - return thread = threading.Thread(target=get_dnf_info, args=(widgets[0],)) thread.start() - self._next_check = int(time.time()) + self.parameter("interval", 30*60) def state(self, widget): cnt = 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumblebee-status-1.5.1/bumblebee/modules/github.py new/bumblebee-status-1.6.0/bumblebee/modules/github.py --- old/bumblebee-status-1.5.1/bumblebee/modules/github.py 2017-12-19 18:29:39.000000000 +0100 +++ new/bumblebee-status-1.6.0/bumblebee/modules/github.py 2018-01-07 20:41:14.000000000 +0100 @@ -10,7 +10,6 @@ * github.interval: Interval in minutes """ -import time import functools import bumblebee.input import bumblebee.output @@ -27,8 +26,7 @@ bumblebee.output.Widget(full_text=self.github) ) self._count = 0 - self._interval = int(self.parameter("interval", "5")) - self._nextcheck = 0 + self.interval(5) self._requests = requests.Session() self._requests.headers.update({"Authorization":"token {}".format(self.parameter("token", ""))}) engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE, @@ -41,23 +39,20 @@ return str(self._count) def update(self, _, immediate=False): - if immediate or self._nextcheck < int(time.time()): - self._nextcheck = int(time.time()) + self._interval * 60 + try: + self._count = 0 + 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') + if next_link is not None: + url = next_link.get('url') + else: + break - try: - self._count = 0 - 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') - if next_link is not None: - url = next_link.get('url') - else: - break - - except Exception: - self._count = "n/a" + except Exception: + self._count = "n/a" # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumblebee-status-1.5.1/bumblebee/modules/hipchat.py new/bumblebee-status-1.6.0/bumblebee/modules/hipchat.py --- old/bumblebee-status-1.5.1/bumblebee/modules/hipchat.py 2017-12-19 18:29:39.000000000 +0100 +++ new/bumblebee-status-1.6.0/bumblebee/modules/hipchat.py 2018-01-07 20:41:14.000000000 +0100 @@ -8,7 +8,6 @@ * hipchat.interval: Refresh interval in minutes (defaults to 5) """ -import time import functools import bumblebee.input import bumblebee.output @@ -27,8 +26,7 @@ bumblebee.output.Widget(full_text=self.output) ) self._count = 0 - self._interval = int(self.parameter("interval", "5")) - self._nextcheck = 0 + self.interval(5) self._requests = requests.Session() self._requests.headers.update({"Authorization":"Bearer {}".format(self.parameter("token", ""))}) @@ -40,16 +38,12 @@ return str(self._count) def update(self, _, immediate=False): - if immediate or self._nextcheck < int(time.time()): - self._nextcheck = int(time.time()) + self._interval * 60 - - try: - self._count = 0 - items = self._requests.get(HIPCHAT_API_URL).json().get('items') - self._count = sum([item.get('unreadCount').get('count') for item in items]) - - except Exception: - self._count = "n/a" + try: + self._count = 0 + items = self._requests.get(HIPCHAT_API_URL).json().get('items') + self._count = sum([item.get('unreadCount').get('count') for item in items]) + except Exception: + self._count = "n/a" # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumblebee-status-1.5.1/bumblebee/modules/redshift.py new/bumblebee-status-1.6.0/bumblebee/modules/redshift.py --- old/bumblebee-status-1.5.1/bumblebee/modules/redshift.py 2017-12-19 18:29:39.000000000 +0100 +++ new/bumblebee-status-1.6.0/bumblebee/modules/redshift.py 2018-01-07 20:41:14.000000000 +0100 @@ -6,43 +6,78 @@ * redshift """ +import threading + import bumblebee.input import bumblebee.output import bumblebee.engine +def is_terminated(): + for thread in threading.enumerate(): + if thread.name == "MainThread" and not thread.is_alive(): + return True + return False + +def get_redshift_value(widget): + while True: + if is_terminated(): + return + widget.get("condition").acquire() + while True: + try: + widget.get("condition").wait(1) + except RuntimeError: + continue + break + widget.get("condition").release() + + try: + res = bumblebee.util.execute("redshift -p") + except Exception: + res = "" + widget.set("temp", "n/a") + widget.set("transition", None) + for line in res.split("\n"): + if "temperature" in line.lower(): + widget.set("temp", line.split(" ")[2]) + if "period" in line.lower(): + state = line.split(" ")[1].lower() + if "day" in state: + widget.set("state", "day") + elif "night" in state: + widget.set("state", "night") + else: + widget.set("state", "transition") + widget.set("transition", " ".join(line.split(" ")[2:])) + class Module(bumblebee.engine.Module): def __init__(self, engine, config): - super(Module, self).__init__(engine, config, - bumblebee.output.Widget(full_text=self.text) - ) + widget = bumblebee.output.Widget(full_text=self.text) + super(Module, self).__init__(engine, config, widget) self._text = "" - self._state = "transition" + self._condition = threading.Condition() + widget.set("condition", self._condition) + self._thread = threading.Thread(target=get_redshift_value, args=(widget,)) + self._thread.start() + self._condition.acquire() + self._condition.notify() + self._condition.release() def text(self, widget): return "{}".format(self._text) def update(self, widgets): - result = bumblebee.util.execute("redshift -p") - - temp = "" - transition = "" - for line in result.split("\n"): - if "temperature" in line.lower(): - temp = line.split(" ")[2] - if "period" in line.lower(): - state = line.split(" ")[1].lower() - if "day" in state: - self._state = "day" - elif "night" in state: - self._state = "night" - else: - self._state = "transition" - transition = " ".join(line.split(" ")[2:]) + widget = widgets[0] + self._condition.acquire() + self._condition.notify() + self._condition.release() + temp = widget.get("temp", "n/a") self._text = temp + transition = widget.get("transition", None) if transition: self._text = "{} {}".format(temp, transition) def state(self, widget): - return self._state + return widget.get("state", None) # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumblebee-status-1.5.1/bumblebee/modules/stock.py new/bumblebee-status-1.6.0/bumblebee/modules/stock.py --- old/bumblebee-status-1.5.1/bumblebee/modules/stock.py 2017-12-19 18:29:39.000000000 +0100 +++ new/bumblebee-status-1.6.0/bumblebee/modules/stock.py 2018-01-07 20:41:14.000000000 +0100 @@ -19,26 +19,31 @@ import requests +import logging + class Module(bumblebee.engine.Module): def __init__(self, engine, config): super(Module, self).__init__(engine, config, bumblebee.output.Widget(full_text=self.value) ) - self._symbols = self.parameter("symbols", "") - self._change = bumblebee.util.asbool(self.parameter("change", True)) + self._symbols = self.parameter('symbols', '') + self._change = bumblebee.util.asbool(self.parameter('change', True)) self._currencies = self.parameter('currencies', None) self._baseurl = 'http://download.finance.yahoo.com/d/quotes.csv' self._value = self.fetch() + self.interval(60) if not self._currencies: self._currencies = '$' * len(self._symbols) # The currencies could be unicode, like the € symbol. Convert to a unicode object. - if hasattr(self._currencies, "decode"): - self._currencies = self._currencies.decode("utf-8", "ignore") + if hasattr(self._currencies, 'decode'): + self._currencies = self._currencies.decode('utf-8', 'ignore') def value(self, widget): results = [] + if not self._value: + return 'n/a' for i, val in enumerate(self._value.split('\n')): try: currency_symbol = self._currencies[i] @@ -55,7 +60,8 @@ url += 'c1' return requests.get(url).text.strip() else: - return '' + logging.error('unable to retrieve stock exchange rate') + return None def update(self, widgets): self._value = self.fetch() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumblebee-status-1.5.1/bumblebee/modules/weather.py new/bumblebee-status-1.6.0/bumblebee/modules/weather.py --- old/bumblebee-status-1.5.1/bumblebee/modules/weather.py 2017-12-19 18:29:39.000000000 +0100 +++ new/bumblebee-status-1.6.0/bumblebee/modules/weather.py 2018-01-07 20:41:14.000000000 +0100 @@ -7,7 +7,6 @@ * requests Parameters: - * weather.interval: Interval (in minutes) for updating weather information * weather.location: Set location (ISO 3166 country code), defaults to 'auto' for getting location from http://ipinfo.io * weather.unit: metric (default), kelvin, imperial * weather.apikey: API key from http://api.openweathermap.org @@ -18,7 +17,6 @@ import bumblebee.engine import re import json -import time try: import requests from requests.exceptions import RequestException @@ -34,10 +32,9 @@ self._apikey = self.parameter("apikey", "af7bfe22287c652d032a3064ffa44088") self._location = self.parameter("location", "auto") self._city = self.parameter("location", "") - self._interval = int(self.parameter("interval", "15")) self._unit = self.parameter("unit", "metric") - self._nextcheck = 0 self._valid = False + self.interval(15) def _unit_suffix(self): if self._unit == "metric": @@ -82,27 +79,24 @@ return [] def update(self, widgets): - timestamp = int(time.time()) - if self._nextcheck < timestamp: - try: - self._nextcheck = timestamp + self._interval*60 - 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 == "auto": - location_url = "http://ipinfo.io/json" - location = json.loads(requests.get(location_url).text) - coord = location["loc"].split(",") - self._city = location["city"] - weather_url = "{url}&lat={lat}&lon={lon}".format(url=weather_url, lat=coord[0], lon=coord[1]) - else: - weather_url = "{url}&q={city}".format(url=weather_url, city=self._location) - weather = json.loads(requests.get(weather_url).text) - self._temperature = int(weather['main']['temp']) - self._weather = weather['weather'][0]['main'].lower() - self._valid = True - except RequestException: - self._valid = False - except Exception: - self._valid = False + 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 == "auto": + location_url = "http://ipinfo.io/json" + location = json.loads(requests.get(location_url).text) + coord = location["loc"].split(",") + self._city = location["city"] + weather_url = "{url}&lat={lat}&lon={lon}".format(url=weather_url, lat=coord[0], lon=coord[1]) + else: + weather_url = "{url}&q={city}".format(url=weather_url, city=self._location) + weather = json.loads(requests.get(weather_url).text) + self._temperature = int(weather['main']['temp']) + self._weather = weather['weather'][0]['main'].lower() + self._valid = True + except RequestException: + self._valid = False + except Exception: + self._valid = False # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumblebee-status-1.5.1/bumblebee/theme.py new/bumblebee-status-1.6.0/bumblebee/theme.py --- old/bumblebee-status-1.5.1/bumblebee/theme.py 2017-12-19 18:29:39.000000000 +0100 +++ new/bumblebee-status-1.6.0/bumblebee/theme.py 2018-01-07 20:41:14.000000000 +0100 @@ -6,7 +6,16 @@ import glob import copy import json +import yaml import io +import re +import logging + +try: + import requests + from requests.exceptions import RequestException +except ImportError: + pass import bumblebee.error @@ -36,11 +45,36 @@ self._cycle = {} self._prevbg = None self._colorset = {} + + self.load_symbols() + data = self.load(name) if not data: raise bumblebee.error.ThemeLoadError("no such theme") self._init(data) + def load_symbols(self): + self._symbols = {} + path = os.path.expanduser("~/.config/bumblebee-status/") + try: + os.makedirs(path) + except Exception: + pass + try: + if os.path.exists("{}/symbols.json".format(path)): + data = json.load(io.open("{}/symbols.json".format(path))) + self._symbols = {} + for icon in data["icons"]: + code = int(icon["unicode"], 16) + try: + code = unichr(code) + except Exception: + code = chr(code) + self._symbols["${{{}}}".format(icon["id"])] = code + self._symbols["${{{}}}".format(icon["name"])] = code + except Exception as e: + logging.error("failed to load symbols: {}".format(str(e))) + def _init(self, data): """Initialize theme from data structure""" self._theme = data @@ -131,7 +165,15 @@ result = {} for path in theme_path(): self._merge(result, self.load(name, path="{}/icons/".format(path))) - return result + + return self._replace_symbols(result) + + def _replace_symbols(self, data): + rep = json.dumps(data) + tokens = re.findall(r"\${[^}]+}", rep) + for token in tokens: + rep = rep.replace(token, self._symbols[token]) + return json.loads(rep) def load(self, name, path=theme_path()): """Load and parse a theme file""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/bumblebee-status-1.5.1/runtests.sh new/bumblebee-status-1.6.0/runtests.sh --- old/bumblebee-status-1.5.1/runtests.sh 2017-12-19 18:29:39.000000000 +0100 +++ new/bumblebee-status-1.6.0/runtests.sh 2018-01-07 20:41:14.000000000 +0100 @@ -1,11 +1,11 @@ #!/bin/sh echo "testing with $(python2 -V 2>&1)" -python2 $(which nosetests) --rednose -v --with-coverage --cover-erase tests/ +python2 $(which nosetests) -v --with-coverage --cover-erase tests/ if [ $? == 0 ]; then echo echo "testing with $(python3 -V 2>&1)" - python3 $(which nosetests-3) --rednose -v --with-coverage --cover-erase tests/ + python3 $(which nosetests) -v --with-coverage --cover-erase tests/ fi