Hello community, here is the log from the commit of package when-command for openSUSE:Factory checked in at 2017-05-10 20:54:10 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/when-command (Old) and /work/SRC/openSUSE:Factory/.when-command.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "when-command" Wed May 10 20:54:10 2017 rev:7 rq:494350 version:0.9.12~beta5 Changes: -------- --- /work/SRC/openSUSE:Factory/when-command/when-command.changes 2016-08-03 11:44:54.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.when-command.new/when-command.changes 2017-05-10 20:54:12.347619992 +0200 @@ -1,0 +2,15 @@ +Tue May 9 16:45:47 UTC 2017 - sor.ale...@meowr.ru + +- Update to version 0.9.12~beta5 (changes since 0.9.12~beta3): + * When an interval based condition was created and hours were + chosen as time unit, the applet ignored this choice and still + used minutes (gh#almostearthling/when-command#91). + * Introduce some more thorough checks when registering stock and + user events, so that unsupported D-Bus signals result in + disabled events when all possible implementations have been + tried for. This resulted in a more portable way to handle + battery related events, that weren't actually functioning on + Ubuntu 16.04 due to changes in the D-Bus implementation + (gh#almostearthling/when-command#92). + +------------------------------------------------------------------- Old: ---- when-command-0.9.12-beta.3.tar.gz New: ---- when-command-0.9.12-beta.5.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ when-command.spec ++++++ --- /var/tmp/diff_new_pack.rSUDo8/_old 2017-05-10 20:54:13.395472126 +0200 +++ /var/tmp/diff_new_pack.rSUDo8/_new 2017-05-10 20:54:13.399471562 +0200 @@ -1,7 +1,7 @@ # # spec file for package when-command # -# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,9 +16,9 @@ # -%define _version 0.9.12-beta.3 +%define _version 0.9.12-beta.5 Name: when-command -Version: 0.9.12~beta3 +Version: 0.9.12~beta5 Release: 0 Summary: Configurable user task scheduler License: BSD-3-Clause @@ -66,7 +66,7 @@ python3 setup.py install \ --root=%{buildroot} --prefix=%{_prefix} -install -Dm 0644 %{name}.appdata.xml \ +install -Dpm 0644 %{name}.appdata.xml \ %{buildroot}%{_datadir}/appdata/%{name}.appdata.xml mkdir -p %{buildroot}%{_docdir}/ ++++++ when-command-0.9.12-beta.3.tar.gz -> when-command-0.9.12-beta.5.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/when-command-0.9.12-beta.3/README.md new/when-command-0.9.12-beta.5/README.md --- old/when-command-0.9.12-beta.3/README.md 2016-06-15 23:35:46.000000000 +0200 +++ new/when-command-0.9.12-beta.5/README.md 2016-09-21 20:30:09.000000000 +0200 @@ -20,6 +20,8 @@ $ sudo apt-get install when-command ``` +> *Note:* on Ubuntu 16.04 *"Xenial Xerus"* the required dependency `python-support` is not available through regular updates. However it can be installed by [downloading](http://launchpadlibrarian.net/109052632/python-support_1.0.15_all.deb) it from the official [repository](https://launchpad.net/ubuntu/xenial/amd64/python-support/1.0.15) and issuing `sudo dpkg --install python-support_1.0.15_all.deb` on a terminal window from the download directory, before attempting to install **When** using the provided PPA. + If the PPA is used, **When** can be started from the *Dash* immediately: once started, it can be configured for autostart using the *Settings* dialog box. ## Alternate Interface diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/when-command-0.9.12-beta.3/share/when-command/when-command.py new/when-command-0.9.12-beta.5/share/when-command/when-command.py --- old/when-command-0.9.12-beta.3/share/when-command/when-command.py 2016-06-15 23:35:46.000000000 +0200 +++ new/when-command-0.9.12-beta.5/share/when-command/when-command.py 2016-09-21 20:30:09.000000000 +0200 @@ -78,8 +78,8 @@ # * the first holds the version ID that build utilities can extract # * the second one includes a message that is used both as a commit message # and as a tag-associated message (in `git tag -m`) -APPLET_VERSION = '0.9.12~beta.3' -APPLET_TAGDESC = 'Work around an issue occurring on unsupported locales' +APPLET_VERSION = '0.9.12~beta.5' +APPLET_TAGDESC = 'Signal registration verification and portable battery events' # logging constants LOG_FORMAT = '%(asctime)s %(levelname)s: %(message)s' @@ -198,6 +198,19 @@ NM_STATE_CONNECTED_SITE = 60 NM_STATE_CONNECTED_GLOBAL = 70 +# DBus battery states: see https://upower.freedesktop.org/docs/Device.html +BATTERY_UPOWER_UNKNOWN = 0 +BATTERY_UPOWER_CHARGING = 1 +BATTERY_UPOWER_DISCHARGING = 2 +BATTERY_UPOWER_EMPTY = 3 +BATTERY_UPOWER_FULL = 4 +BATTERY_UPOWER_PENDINGCHARGE = 5 +BATTERY_UPOWER_PENDINGDISCHARGE = 6 + +# this will be changed at first battery check if any +BATTERY_LEVEL_LOW = None +BATTERY_LEVEL_LOW_DEFAULT = 20 + # file notification constants: from inotify.h here are the constants # IN_ACCESS 0x00000001 /* File was accessed */ # IN_MODIFY 0x00000002 /* File was modified */ @@ -253,6 +266,11 @@ current_changed_path = None current_deferred_changed_paths = None +# battery status checks +current_battery_status_charging = False +current_battery_status_discharging = False +current_battery_status_low = False + applet_log_handler = logging.NullHandler() applet_log_formatter = logging.Formatter(fmt=LOG_FORMAT, datefmt='%Y-%m-%d %H:%M:%S') applet_log_handler.setFormatter(applet_log_formatter) @@ -367,55 +385,69 @@ lambda iface, *args: iface.state() in [NM_STATE_DISCONNECTED] ), ], + # see the following post for a hint on alternate interfaces + # on reddit: https://www.reddit.com/r/Fedora/comments/3bssp9/ EVENT_SYSTEM_BATTERY_CHARGE: [ event_definition( EVENT_SYSTEM_BATTERY_CHARGE, True, 'system', - 'org.freedesktop.UPower', '/org/freedesktop/UPower', - 'org.freedesktop.UPower', 'Changed', + 'org.freedesktop.UPower', + '/org/freedesktop/UPower/devices/battery_BAT0', + 'org.freedesktop.UPower.Device', 'Changed', None, - lambda iface, *args: ( - not iface.proxy_object.Get( - 'org.freedesktop.UPower', 'OnBattery', - dbus_interface='org.freedesktop.DBus.Properties') and - not iface.proxy_object.Get( - 'org.freedesktop.UPower', 'OnLowBattery', - dbus_interface='org.freedesktop.DBus.Properties') - ) + lambda iface, *args: battery_changed_charging(iface) + ), + # Xenial + event_definition( + EVENT_SYSTEM_BATTERY_CHARGE, True, + 'system', + 'org.freedesktop.UPower', + '/org/freedesktop/UPower/devices/battery_BAT0', + 'org.freedesktop.DBus.Properties', 'PropertiesChanged', + None, + lambda iface, *args: battery_changed_charging(iface) ), ], EVENT_SYSTEM_BATTERY_DISCHARGING: [ event_definition( EVENT_SYSTEM_BATTERY_DISCHARGING, True, 'system', - 'org.freedesktop.UPower', '/org/freedesktop/UPower', - 'org.freedesktop.UPower', 'Changed', + 'org.freedesktop.UPower', + '/org/freedesktop/UPower/devices/battery_BAT0', + 'org.freedesktop.UPower.Device', 'Changed', None, - lambda iface, *args: ( - iface.proxy_object.Get( - 'org.freedesktop.UPower', 'OnBattery', - dbus_interface='org.freedesktop.DBus.Properties') and - not iface.proxy_object.Get( - 'org.freedesktop.UPower', 'OnLowBattery', - dbus_interface='org.freedesktop.DBus.Properties') - ) + lambda iface, *args: battery_changed_discharging(iface) + ), + # Xenial + event_definition( + EVENT_SYSTEM_BATTERY_DISCHARGING, True, + 'system', + 'org.freedesktop.UPower', + '/org/freedesktop/UPower/devices/battery_BAT0', + 'org.freedesktop.DBus.Properties', 'PropertiesChanged', + None, + lambda iface, *args: battery_changed_discharging(iface) ), ], EVENT_SYSTEM_BATTERY_LOW: [ event_definition( EVENT_SYSTEM_BATTERY_LOW, True, 'system', - 'org.freedesktop.UPower', '/org/freedesktop/UPower', - 'org.freedesktop.UPower', 'Changed', + 'org.freedesktop.UPower', + '/org/freedesktop/UPower/devices/battery_BAT0', + 'org.freedesktop.UPower.Device', 'Changed', None, - lambda iface, *args: ( - iface.proxy_object.Get( - 'org.freedesktop.UPower', 'OnBattery', - dbus_interface='org.freedesktop.DBus.Properties') and - iface.proxy_object.Get( - 'org.freedesktop.UPower', 'OnLowBattery', - dbus_interface='org.freedesktop.DBus.Properties') - ) + lambda iface, *args: battery_changed_low(iface) + ), + # Xenial + event_definition( + EVENT_SYSTEM_BATTERY_LOW, True, + 'system', + 'org.freedesktop.UPower', + '/org/freedesktop/UPower/devices/battery_BAT0', + 'org.freedesktop.DBus.Properties', 'PropertiesChanged', + None, + lambda iface, *args: battery_changed_low(iface) ), ], EVENT_SYSTEM_DEVICE_ATTACH: [ @@ -927,6 +959,90 @@ ############################################################################# +# battery status retrieval utilities +def check_battery_low(level): + global BATTERY_LEVEL_LOW + if BATTERY_LEVEL_LOW is None: + try: + setting = Gio.Settings.new( + 'org.gnome.settings-daemon.plugins.power') + BATTERY_LEVEL_LOW = setting.get_int('percentage-low') + except: + BATTERY_LEVEL_LOW = BATTERY_LEVEL_LOW_DEFAULT + applet_log.info("MAIN: battery low alert level is set to %s" % BATTERY_LEVEL_LOW) + return level <= BATTERY_LEVEL_LOW + + +def battery_changed_discharging(iface): + global current_battery_status_charging + global current_battery_status_discharging + global current_battery_status_low + value = iface.proxy_object.Get( + 'org.freedesktop.UPower.Device', 'State', + dbus_interface='org.freedesktop.DBus.Properties') + if value in [BATTERY_UPOWER_DISCHARGING, + BATTERY_UPOWER_PENDINGDISCHARGE, + BATTERY_UPOWER_EMPTY]: + if not current_battery_status_discharging: + applet_log.info("MAIN: battery status changed to DISCHARGING") + current_battery_status_charging = False + current_battery_status_discharging = True + return True + else: + return False + else: + current_battery_status_discharging = False + return False + + +def battery_changed_charging(iface): + global current_battery_status_charging + global current_battery_status_discharging + global current_battery_status_low + value = iface.proxy_object.Get( + 'org.freedesktop.UPower.Device', 'State', + dbus_interface='org.freedesktop.DBus.Properties') + if value in [BATTERY_UPOWER_CHARGING, + BATTERY_UPOWER_PENDINGCHARGE, + BATTERY_UPOWER_FULL]: + if not current_battery_status_charging: + applet_log.info("MAIN: battery status changed to CHARGING") + current_battery_status_charging = True + current_battery_status_discharging = False + current_battery_status_low = False + return True + else: + return False + else: + current_battery_status_charging = False + return False + + +def battery_changed_low(iface): + global current_battery_status_charging + global current_battery_status_discharging + global current_battery_status_low + if current_battery_status_discharging: + charge = iface.proxy_object.Get( + 'org.freedesktop.UPower.Device', 'Percentage', + dbus_interface='org.freedesktop.DBus.Properties') + if check_battery_low(charge): + if not current_battery_status_low: + applet_log.info("MAIN: battery status changed to LOW") + current_battery_status_charging = False + current_battery_status_low = True + return True + else: + return False + else: + current_battery_status_low = False + return False + else: + current_battery_status_low = False + return False + + +############################################################################# # item operations functions # wrapper around removal function, accepts list of '[type:]name' or single str @@ -4229,16 +4345,32 @@ elif self.bus == 'system': bus = dbus.SystemBus() else: - self._error("NTBS: invalid bus specification %s: not registering %s:%s handler" % (self.bus, self.interface, self.signal)) + self._error("NTBS: invalid bus specification %s: not registering [%s:%s]%s:%s handler" % (self.bus, self.bus_name, self.bus_path, self.interface, self.signal)) return None proxy = bus.get_object(self.bus_name, self.bus_path) + # introspect interface to verify that signal is handled (ugly) + # (see: https://developer.gnome.org/glibmm/stable/classGio_1_1DBus_1_1NodeInfo.html) + inspect = dbus.Interface(proxy, + 'org.freedesktop.DBus.Introspectable') + nodeinfo = Gio.DBusNodeInfo.new_for_xml(inspect.Introspect()) + if nodeinfo is not None: + siglist = nodeinfo.lookup_interface(self.interface).signals + if self.signal not in [x.name for x in siglist]: + self._warning("signal not found registering [%s:%s]%s:%s handler" % (self.bus_name, self.bus_path, self.interface, self.signal)) + return None + else: + self._warning("introspection not supported registering [%s:%s]%s:%s handler" % (self.bus_name, self.bus_path, self.interface, self.signal)) + return None manager = dbus.Interface(proxy, self.interface) self.signal_match = manager.connect_to_signal( self.signal, self.signal_handler_callback) - self._info("signal handler %s:%s correctly registered" % (self.interface, self.signal)) + self._info("signal handler [%s:%s]%s:%s correctly registered" % (self.bus_name, self.bus_path, self.interface, self.signal)) return manager except dbus.exceptions.DBusException: - self._warning("error registering %s:%s handler" % (self.interface, self.signal)) + self._warning("DBus error registering [%s:%s]%s:%s handler" % (self.bus_name, self.bus_path, self.interface, self.signal)) + return None + except Exception as e: + self._warning("error registering [%s:%s]%s:%s handler (%s)" % (self.bus_name, self.bus_path, self.interface, self.signal, _x(e))) return None def unregister(self): @@ -4379,12 +4511,12 @@ # convert provided callback to something that never raises exceptions def _callback_normalize(self, f): - def _normalized(proxy, *args): + def _normalized(iface, *args): if not self.registered: self._debug("stock signal test skipped: not registered") return False try: - return bool(f(proxy, *args)) + return bool(f(iface, *args)) except Exception as e: self._info("failed stock signal test with exception: %s" % _x(e)) return False @@ -5135,7 +5267,7 @@ idx = o('cbType').get_active() if idx == 0: v = int(o('txtInterval').get_text()) - if o('cbTimeUnit').get_active == 0: + if o('cbTimeUnit').get_active() == 0: interval = v * 60 * 60 else: interval = v * 60