Merge lp:~lottanzb/lottanzb/inhibit-suspending-plugin into lp:lottanzb/0.5

Proposed by Severin H
Status: Merged
Merged at revision: 937
Proposed branch: lp:~lottanzb/lottanzb/inhibit-suspending-plugin
Merge into: lp:lottanzb/0.5
Diff against target: 322 lines (+283/-1)
4 files modified
NEWS (+8/-0)
README (+4/-0)
lottanzb/plugins/__init__.py (+1/-1)
lottanzb/plugins/inhibit_suspending/__init__.py (+270/-0)
To merge this branch: bzr merge lp:~lottanzb/lottanzb/inhibit-suspending-plugin
Reviewer Review Type Date Requested Status
Severin H Approve
Marcel de Vries (community) Approve
Review via email: mp+17793@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Severin H (severinh) wrote :

While all D-Bus operations seem to be properly done, I haven't actually tested the plug-in yet (by not doing any input for a few minutes while downloading). Also, the plug-in will need to be tested on Ubuntu 9.04 (or similar) as a different (older) power management API is used there.

So this merge proposal is mainly meant to be a call to testers. ;-)

891. By Severin H

Update NEWS.

Revision history for this message
Severin H (severinh) wrote :

I seem to have found a bug in gnome-session, preventing the plug-in from working properly on Ubuntu 9.10 and 10.04: https://bugs.edge.launchpad.net/ubuntu/+source/gnome-session/+bug/510907

There is a work-around, but I'd rather wait until things have been cleared up.

Revision history for this message
Severin H (severinh) wrote :

Looks like this merge is currently blocked. The bug mentioned above has been confirmed and triaged. It looks like it's currently not possible to inhibit suspending on Karmic and Lucid machines. Too bad!

review: Disapprove
892. By Severin H

Prevent the plug-in from being enabled on systems with gnome-power-manager < 2.29.2.

Revision history for this message
Severin H (severinh) wrote :

The bug mentioned above has been fixed upstream. Do you (Sander and Marcel) still think that this plug-in would still be a valuable addition to LottaNZB even though it won't work on Ubuntu 9.10? It works fine on Ubuntu 9.04 and 10.04.

Revision history for this message
Severin H (severinh) :
review: Abstain
893. By Severin H

Add note to NEWS that not all systems are supported by the plug-in.

Revision history for this message
Marcel de Vries (carresmd-deactivatedaccount) wrote :

As you block gnome-power-manager versions below 2.29.2, I couldn't test this as Fedora 12 still uses 2.28.2. However looking at the code, it's fine by me. Once I have set up a Fedora rawhide VM I'll give my definitive review. I'll approve for now, as I'm in a good mood ^^.

review: Approve
Revision history for this message
Severin H (severinh) wrote :

Well, it will most probably not work in the Fedora rawhide VM either, simply because gnome-power-manager 2.29.2 hasn't been released yet. ^^ The fix should be part of the GNOME 2.30 Beta to be released in two days.

What do you think about putting this off to LottaNZB 0.5.4 (if it will be released at all)? I just don't feel comfortable releasing a plug-in that won't work for >75% of our users.

Revision history for this message
Marcel de Vries (carresmd-deactivatedaccount) wrote :

It's probably best to put it off to 0.5.4. If I think about it, I see the bug reports floating in like 'Hey, this plugin isn't working...'.

894. By Severin H

Sync with 0.5.

895. By Severin H

Note about gnome-power-manager version in README.

896. By Severin H

Explicitly mention gnome-power-manager bug ID.

Revision history for this message
Severin H (severinh) wrote :

Now that Ubuntu 10.04 has been released, releasing LottaNZB 0.5.4 with this plug-in seems to be more reasonable. Besides this plug-in, some other minor bugs have been fixed and lots of translations were added and updated.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS'
2--- NEWS 2010-05-11 14:47:56 +0000
3+++ NEWS 2010-05-12 20:51:29 +0000
4@@ -1,6 +1,14 @@
5 LottaNZB 0.5.4 - Development
6 ============================
7
8+- New "Inhibit suspending" plug-in. When enabled, it prevents the computer from
9+ being suspended if there hasn't been any input for a certain amount of time,
10+ but there are still active LottaNZB downloads. This allows you to keep the
11+ computer powered on when you go to bed and let it suspend itself when all
12+ downloads are complete.
13+ Please note that this plug-in doesn't work on all systems. Most importantly,
14+ Ubuntu 9.10 isn't supported, while Ubuntu 9.04 and 10.04 are. The reason for
15+ this is bug #510907 in gnome-power-manager 2.28.
16 - Fix crash of LottaNZB at startup occuring when HellaNZB uses unrar-free to
17 extract downloaded archives. (LP: #577105, thanks to Jim in Chicago for
18 reporting this)
19
20=== modified file 'README'
21--- README 2010-02-15 21:32:25 +0000
22+++ README 2010-05-12 20:51:29 +0000
23@@ -48,6 +48,10 @@
24
25 - python-gnome2 (the gnomevfs module)
26
27+For the 'Inhibit suspending' plug-in:
28+
29+- gnome-power-manager >= 2.29.2 or gnome-power-manager <= 2.24.4
30+
31 The package names may vary depending on your distribution.
32
33 Build LottaNZB
34
35=== modified file 'lottanzb/plugins/__init__.py'
36--- lottanzb/plugins/__init__.py 2010-01-20 22:46:40 +0000
37+++ lottanzb/plugins/__init__.py 2010-05-12 20:51:29 +0000
38@@ -150,7 +150,7 @@
39 plug-in cannot be enabled.
40 """
41
42- if key == "enabled" and value and not self.enabled:
43+ if key == "enabled" and value:
44 try:
45 if self.locked:
46 # The plug-in is locked and can therefore not be enabled
47
48=== added directory 'lottanzb/plugins/inhibit_suspending'
49=== added file 'lottanzb/plugins/inhibit_suspending/__init__.py'
50--- lottanzb/plugins/inhibit_suspending/__init__.py 1970-01-01 00:00:00 +0000
51+++ lottanzb/plugins/inhibit_suspending/__init__.py 2010-05-12 20:51:29 +0000
52@@ -0,0 +1,270 @@
53+# Copyright (C) 2008-2010 LottaNZB Development Team
54+#
55+# This program is free software; you can redistribute it and/or modify
56+# it under the terms of the GNU General Public License as published by
57+# the Free Software Foundation; version 3.
58+#
59+# This program is distributed in the hope that it will be useful,
60+# but WITHOUT ANY WARRANTY; without even the implied warranty of
61+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
62+# GNU General Public License for more details.
63+#
64+# You should have received a copy of the GNU General Public License
65+# along with this program; if not, write to the Free Software
66+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
67+
68+import re
69+
70+import logging
71+log = logging.getLogger(__name__)
72+
73+try:
74+ import dbus
75+except ImportError:
76+ dbus = None
77+
78+from subprocess import Popen, PIPE
79+from distutils.version import StrictVersion
80+
81+from lottanzb.plugins import PluginBase, PluginEnablingError
82+from lottanzb.util import _
83+from lottanzb.modes import standalone
84+
85+class Plugin(PluginBase):
86+ title = _("Inhibit suspending")
87+ description = _("Prevents the computer from being suspended while "
88+ "downloading.")
89+ author = _("LottaNZB Development Team")
90+ requires_modes = [standalone.Mode]
91+
92+ def __init__(self, app, config):
93+ # Holds an `InhibitionProvider` if it's possible to instantiate one.
94+ self._provider = None
95+
96+ PluginBase.__init__(self, app, config)
97+
98+ self.connect_when_enabled(self.app.backend, "updated",
99+ self.on_backend_updated)
100+
101+ def import_dependencies(self):
102+ """
103+ Make sure that the D-Bus module is available on the user's machine.
104+
105+ Try to set up an `InhibitionProvider` that provides the methods to
106+ inhibit or uninhibit suspending.
107+ """
108+
109+ global dbus
110+
111+ if not dbus:
112+ import dbus
113+
114+ # A provider should only be set up once, but this method may be called
115+ # several times.
116+ if self._provider is None:
117+ self._setup_provider()
118+
119+ def _setup_provider(self):
120+ inhibition_providers_classes = (
121+ GnomeSessionInhibitionProvider,
122+ HALInhibitionProvider
123+ )
124+
125+ for inhibition_providers_class in inhibition_providers_classes:
126+ try:
127+ provider = inhibition_providers_class("lottanzb")
128+ except InhibitionProviderError, error:
129+ # Try the next provider class.
130+ pass
131+ else:
132+ self._provider = provider
133+
134+ if self._provider is None:
135+ # Bad luck.
136+ raise PluginEnablingError(self, _("Your desktop environment "
137+ "isn't supported by the plug-in."))
138+
139+ def refresh(self):
140+ """
141+ Inhibit suspending if the plug-in is enabled and there are active
142+ downloads or an active post-processing operation. Allows suspending
143+ otherwise.
144+ """
145+
146+ if self._provider is not None:
147+ if self.enabled:
148+ downloads = self.app.backend.downloads
149+ inhibit = bool(downloads.get_processing() \
150+ or (downloads.get_active_download() \
151+ and not self.app.backend.paused))
152+
153+ if inhibit:
154+ self.inhibit()
155+ else:
156+ self.uninhibit()
157+ else:
158+ self.uninhibit()
159+
160+ def on_backend_updated(self, backend):
161+ """
162+ Check if suspending needs to be inhibited/uninhibited whenever the
163+ download list is updated.
164+ """
165+
166+ self.refresh()
167+
168+ def inhibit(self):
169+ """Try to prevent the computer from being suspended."""
170+
171+ if not self._provider.is_inhibited():
172+ reason = _("Download activity")
173+
174+ try:
175+ self._provider.inhibit(reason)
176+ except InhibitionProviderError, error:
177+ log.warning(_("Could not disallow suspending: %s") % str(error))
178+ else:
179+ log.info(_("Disallowing suspending."))
180+
181+ def uninhibit(self):
182+ """Allow the computer to be suspended."""
183+
184+ if self._provider.is_inhibited():
185+ try:
186+ self._provider.uninhibit()
187+ except InhibitionProviderError, error:
188+ log.warning(_("Could not reallow suspending: %s") % \
189+ str(error))
190+ else:
191+ log.info(_("Allowing suspending."))
192+
193+
194+class InhibitionProvider:
195+ def __init__(self, application):
196+ self.application = application
197+
198+ def inhibit(self, reason=""):
199+ raise NotImplementedError
200+
201+ def uninhibit(self):
202+ raise NotImplementedError
203+
204+ def is_inhibited(self):
205+ raise NotImplementedError
206+
207+ def tear_down(self):
208+ pass
209+
210+
211+class HALInhibitionProvider(InhibitionProvider):
212+ def __init__(self, application):
213+ InhibitionProvider.__init__(self, application)
214+
215+ try:
216+ session_bus = dbus.SessionBus()
217+ interface_name = "org.freedesktop.PowerManagement.Inhibit"
218+ proxy = session_bus.get_object(
219+ "org.freedesktop.PowerManagement",
220+ "/org/freedesktop/PowerManagement/Inhibit"
221+ )
222+
223+ self._interface = dbus.Interface(proxy, interface_name)
224+ self._cookie = None
225+ except dbus.exceptions.DBusException, error:
226+ raise InhibitionProviderError()
227+
228+ def inhibit(self, reason=""):
229+ """Try to prevent the computer from being suspended."""
230+
231+ try:
232+ self._cookie = self._interface.Inhibit(self.application, reason)
233+ except dbus.exceptions.DBusException, error:
234+ raise InhibitionProviderError(error.message)
235+
236+ def uninhibit(self):
237+ """Allow the computer to be suspended."""
238+
239+ try:
240+ self._interface.UnInhibit(self._cookie)
241+ except dbus.exceptions.DBusException, error:
242+ raise InhibitionProviderError(error.message)
243+ finally:
244+ self._cookie = None
245+
246+ def is_inhibited(self):
247+ return bool(self._cookie is not None)
248+
249+
250+class GnomeSessionInhibitionProvider(InhibitionProvider):
251+ VERSION_PATTERN = re.compile("\d[\d\.]*")
252+
253+ # The GNOME Power Manager didn't actually use the SessionManager D-Bus API
254+ # to check if there are any suspending inhibitors until version 2.29.2.
255+ # Thus, this `InhibitionProvider` will not work on systems like Ubuntu 9.10
256+ # that use the GNOME 2.28 or older.
257+ # See https://bugzilla.gnome.org/show_bug.cgi?id=607748
258+ MIN_GPM_VERSION = StrictVersion("2.29.2")
259+
260+ def __init__(self, application):
261+ InhibitionProvider.__init__(self, application)
262+
263+ try:
264+ process = Popen(["gnome-power-manager", "--version"], stdout=PIPE)
265+ process.wait()
266+ except OSError, error:
267+ raise InhibitionProviderError(str(error))
268+ else:
269+ match = self.VERSION_PATTERN.search(process.stdout.read())
270+
271+ # Don't raise an `InhibitionProviderError` if the version output
272+ # doesn't have the expected format, so that potential future changes
273+ # to the GNOME Power Manager don't erroneously fail the check.
274+ if match and StrictVersion(match.group()) < self.MIN_GPM_VERSION:
275+ raise InhibitionProviderError()
276+
277+ try:
278+ session_bus = dbus.SessionBus()
279+ interface_name = "org.gnome.SessionManager"
280+ proxy = session_bus.get_object(
281+ "org.gnome.SessionManager",
282+ "/org/gnome/SessionManager"
283+ )
284+
285+ self._interface = dbus.Interface(proxy, interface_name)
286+ self._client_id = self._interface.RegisterClient(self.application,
287+ self.application)
288+ self._cookie = None
289+ except dbus.exceptions.DBusException, error:
290+ raise InhibitionProviderError(error.message)
291+
292+ def inhibit(self, reason=""):
293+ """Try to prevent the computer from being suspended."""
294+
295+ try:
296+ self._cookie = self._interface.Inhibit(self.application, 0, reason,
297+ 0x4)
298+ except dbus.exceptions.DBusException, error:
299+ raise InhibitionProviderError(error.message)
300+
301+ def uninhibit(self):
302+ """Allow the computer to be suspended."""
303+
304+ try:
305+ self._interface.Uninhibit(self._cookie)
306+ except dbus.exceptions.DBusException, error:
307+ raise InhibitionProviderError(error.message)
308+ finally:
309+ self._cookie = None
310+
311+ def tear_down(self):
312+ try:
313+ self._interface.UnregisterClient(self._client_id)
314+ except dbus.exceptions.DBusException, error:
315+ raise InhibitionProviderError(error.message)
316+
317+ def is_inhibited(self):
318+ return bool(self._cookie is not None)
319+
320+
321+class InhibitionProviderError(Exception):
322+ pass

Subscribers

People subscribed via source and target branches

to all changes: