Merge lp:~thisfred/ubuntuone-client/lp-702055 into lp:ubuntuone-client

Proposed by Eric Casteleijn
Status: Merged
Approved by: dobey
Approved revision: 851
Merged at revision: 854
Proposed branch: lp:~thisfred/ubuntuone-client/lp-702055
Merge into: lp:ubuntuone-client
Diff against target: 501 lines (+173/-63)
6 files modified
tests/platform/linux/test_messaging.py (+8/-3)
tests/status/test_aggregator.py (+90/-27)
ubuntuone/platform/linux/messaging.py (+28/-11)
ubuntuone/platform/windows/messaging.py (+15/-8)
ubuntuone/status/aggregator.py (+28/-12)
ubuntuone/status/messaging.py (+4/-2)
To merge this branch: bzr merge lp:~thisfred/ubuntuone-client/lp-702055
Reviewer Review Type Date Requested Status
Natalia Bidart (community) Approve
Alejandro J. Cura (community) Approve
Review via email: mp+48987@code.launchpad.net

Commit message

This adds notifications and messaging on new incoming shares and UDFs.

Description of the change

This adds notifications and messaging on new incoming shares and UDFs.

To post a comment you must log in.
Revision history for this message
Alejandro J. Cura (alecu) wrote :

Great branch!

Two small issues:
 * I think that new_share_available in StatusFrontend should also pass _callback to messaging.show_message, just like new_udf_available
 * I think that StatusFrontend._callback should be named more descriptively.

Otherwise great work :-)

review: Needs Fixing
Revision history for this message
Alejandro J. Cura (alecu) wrote :

Also, StatusAggregator.restart_progress_bubble should be called after any send_notification. In fact, I believe we should make an aggregating/updating mechanism (like the one in FileDiscoveryBubble) in an upcoming branch, so if more events are received they are shown on the current notification.

For instance, turning on the computer and finding out 3 new udfs are available. With this branch we'll see three bubbles one after the other, each popping up immediately after the previous is hidden. With an updating mechanism we would only see one bubble, and the message would be updated as soon as the second and third udfs are found.

Revision history for this message
Eric Casteleijn (thisfred) wrote :

The reason share_available does not pass the callback, is because it does not need a special callback method that updates the count like new_udf. If no callback is passed in, the default is used, which opens the volumes tab in the control panel and hides the message.

I'll rename the _callback method.

And yes, we probably will want to aggregate the notifications (though maybe not for new shares.) I'll look into that on a new branch.

Revision history for this message
Eric Casteleijn (thisfred) wrote :

method renamed in r851

Revision history for this message
Alejandro J. Cura (alecu) wrote :

+1

review: Approve
Revision history for this message
Natalia Bidart (nataliabidart) :
review: Approve
Revision history for this message
Ubuntu One Auto Pilot (otto-pilot) wrote :
Download full text (192.5 KiB)

The attempt to merge lp:~thisfred/ubuntuone-client/lp-702055 into lp:ubuntuone-client failed. Below is the output from the failed tests.

/usr/bin/gnome-autogen.sh
checking for autoconf >= 2.53...
  testing autoconf2.50... not found.
  testing autoconf... found 2.67
checking for automake >= 1.10...
  testing automake-1.11... found 1.11.1
checking for libtool >= 1.5...
  testing libtoolize... found 2.2.6b
checking for intltool >= 0.30...
  testing intltoolize... found 0.41.1
checking for pkg-config >= 0.14.0...
  testing pkg-config... found 0.25
checking for gtk-doc >= 1.0...
  testing gtkdocize... found 1.16
Checking for required M4 macros...
Checking for forbidden M4 macros...
Processing ./configure.ac
Running libtoolize...
libtoolize: putting auxiliary files in `.'.
libtoolize: copying file `./ltmain.sh'
libtoolize: putting macros in AC_CONFIG_MACRO_DIR, `m4'.
libtoolize: copying file `m4/libtool.m4'
libtoolize: copying file `m4/ltoptions.m4'
libtoolize: copying file `m4/ltsugar.m4'
libtoolize: copying file `m4/ltversion.m4'
libtoolize: copying file `m4/lt~obsolete.m4'
Running intltoolize...
Running gtkdocize...
Running aclocal-1.11...
Running autoconf...
Running autoheader...
Running automake-1.11...
Running ./configure --enable-gtk-doc --enable-debug ...
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for style of include used by make... GNU
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking dependency style of gcc... gcc3
checking for library containing strerror... none required
checking for gcc... (cached) gcc
checking whether we are using the GNU C compiler... (cached) yes
checking whether gcc accepts -g... (cached) yes
checking for gcc option to accept ISO C89... (cached) none needed
checking dependency style of gcc... (cached) gcc3
checking build system type... i686-pc-linux-gnu
checking host system type... i686-pc-linux-gnu
checking for a sed that does not truncate output... /bin/sed
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for fgrep... /bin/grep -F
checking for ld used by gcc... /usr/bin/ld
checking if the linker (/usr/bin/ld) is GNU ld... yes
checking for BSD- or MS-compatible name lister (nm)... /usr/bin/nm -B
checking the name lister (/usr/bin/nm -B) interface... BSD nm
checking whether ln -s works... yes
checking the maximum length of command line arguments... 1572864
checking whether the shell understands some XSI constructs... yes
checking whether the shell understands "+="... yes
checking for /usr/bin/ld option to reload object files... -r
checking for objdump... objdump
checking how to recognize dependent libraries...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'tests/platform/linux/test_messaging.py'
2--- tests/platform/linux/test_messaging.py 2011-02-03 17:50:53 +0000
3+++ tests/platform/linux/test_messaging.py 2011-02-09 13:12:13 +0000
4@@ -49,6 +49,7 @@
5 self.mocker.restore()
6 self.mocker.verify()
7
8+ # pylint: disable=R0913
9 def _show_message_setup(self, message_time=None, message_count=None,
10 icon=None, update_count=None, hide=False):
11 """Set up the mocker expectations for show_method."""
12@@ -81,12 +82,15 @@
13 mock_indicator.set_property("draw-attention", "true")
14 mock_server.show()
15 if update_count:
16- mock_indicator.set_property("count", str(update_count))
17+ mock_indicator.get_property("count")
18+ self.mocker.result("1200")
19+ mock_indicator.set_property("count", '2500')
20 if hide:
21 mock_indicator.set_property('draw-attention', 'false')
22 mock_indicator.hide()
23 mock_indicator.show()
24 self.mocker.replay()
25+ # pylint: enable=R0913
26
27 def test_show_message(self):
28 """On message, libnotify receives the proper calls."""
29@@ -116,8 +120,9 @@
30 """On message count update, libnotify receives the proper calls."""
31 self._show_message_setup(message_count='1200', update_count='1300')
32 messaging = Messaging()
33- messaging.show_message(FAKE_SENDER, callback, message_count=1200)
34- messaging.update_count(FAKE_SENDER, 1300)
35+ indicator = messaging.show_message(
36+ FAKE_SENDER, callback, message_count=1200)
37+ messaging.update_count(indicator, 1300)
38
39 def test_hide_message(self):
40 """On message hide, libnotify receives the proper calls."""
41
42=== modified file 'tests/status/test_aggregator.py'
43--- tests/status/test_aggregator.py 2011-02-04 02:25:03 +0000
44+++ tests/status/test_aggregator.py 2011-02-09 13:12:13 +0000
45@@ -25,6 +25,7 @@
46 from ubuntuone.devtools.handlers import MementoHandler
47 from ubuntuone.status import aggregator
48 from ubuntuone.status.notification import AbstractNotification
49+from ubuntuone.status.messaging import AbstractMessaging
50 from ubuntuone.syncdaemon import status_listener
51 from ubuntuone.syncdaemon.volume_manager import Share, UDF
52
53@@ -144,7 +145,7 @@
54 notification]
55 if new_icon is not None:
56 icon = new_icon
57- # we store it as a new notification, to ease testing
58+ # we store it as a new notification, to ease testing
59 notification_params = (new_title, new_message, icon, append)
60 self.notifications_shown.append(notification_params)
61
62@@ -160,30 +161,32 @@
63 return get_instance
64
65
66-class FakeMessaging(object):
67+class FakeMessaging(AbstractMessaging):
68 """A fake messaging class."""
69
70- def __init__(self, application_name="fake app"):
71+ def __init__(self): # pylint: disable=W0231
72 self.messages_shown = {}
73- self.application_name = application_name
74+ self.messages_updated = {}
75
76- def show_message(self, sender, callback, message_time=None,
77+ # pylint: disable=R0913
78+ def show_message(self, sender, callback=None, message_time=None,
79 message_count=None, icon=None):
80 """Show a message to the user."""
81+ if message_count and sender in self.messages_shown:
82+ self.update_count(sender, message_count)
83 self.messages_shown[sender] = (
84 callback, message_time, message_count, icon)
85+ # pylint: enable=R0913
86
87- def update_count(self, sender, new_count):
88+ def update_count(self, sender, add_count):
89 """Update the count for an existing indicator."""
90- callback, message_time, _, icon = self.messages_shown[sender]
91- self.messages_shown[sender] = (
92- callback, message_time, new_count, icon)
93+ self.messages_updated[sender] = (sender, add_count)
94
95
96 class FakeStatusAggregator(object):
97 """A fake status aggregator."""
98
99- def __init__(self, clock):
100+ def __init__(self, clock): # pylint: disable=W0613
101 """Initialize this instance."""
102 self.discovered = 0
103 self.completed = 0
104@@ -523,13 +526,8 @@
105
106 def __init__(self, clock):
107 """Initialize this fake instance."""
108- self.interesting_events = []
109 self.queued_commands = set()
110
111- def interesting_event(self, event):
112- """A new interesting event was found."""
113- self.interesting_events.append(event)
114-
115 def queue_done(self):
116 """The queue completed all operations."""
117 self.queued_commands.clear()
118@@ -554,23 +552,30 @@
119 def setUp(self):
120 """Initialize this test instance."""
121 self.patch(aggregator, "StatusAggregator", FakeAggregator)
122+ self.patch(aggregator, "Notification", FakeNotificationSingleton())
123+ self.patch(aggregator, "Messaging", FakeMessaging)
124 self.fakefsm = None
125 self.fakevm = FakeVolumeManager()
126 self.status_frontend = aggregator.StatusFrontend()
127 self.listener = status_listener.StatusListener(self.fakefsm,
128 self.fakevm,
129 self.status_frontend)
130+
131 def test_file_published(self):
132 """A file published event is processed."""
133 share_id = "fake share id"
134 node_id = "fake node id"
135 is_public = True
136 public_url = "http://fake_public/url"
137-
138 self.listener.handle_AQ_CHANGE_PUBLIC_ACCESS_OK(share_id, node_id,
139 is_public, public_url)
140- event = self.status_frontend.aggregator.interesting_events[0]
141- self.assertIsInstance(event, aggregator.FilePublishingStatus)
142+ self.assertEqual(
143+ 1, len(self.status_frontend.notification.notifications_shown))
144+ self.assertEqual(
145+ (aggregator.UBUNTUONE_TITLE,
146+ 'A file was just made public at http://fake_public/url', None,
147+ False),
148+ self.status_frontend.notification.notifications_shown[0])
149
150 def test_file_unpublished(self):
151 """A file unpublished event is processed."""
152@@ -581,8 +586,12 @@
153
154 self.listener.handle_AQ_CHANGE_PUBLIC_ACCESS_OK(share_id, node_id,
155 is_public, public_url)
156- event = self.status_frontend.aggregator.interesting_events[0]
157- self.assertIsInstance(event, aggregator.FileUnpublishingStatus)
158+ self.assertEqual(
159+ 1, len(self.status_frontend.notification.notifications_shown))
160+ self.assertEqual(
161+ (aggregator.UBUNTUONE_TITLE, 'A file is no longer published', None,
162+ False),
163+ self.status_frontend.notification.notifications_shown[0])
164
165 def test_download_started(self):
166 """A download was added to the queue."""
167@@ -644,22 +653,77 @@
168 def test_new_share_available(self):
169 """A new share is available for subscription."""
170 SHARE_ID = "fake share id"
171- share = Share(volume_id=SHARE_ID)
172+ FAKE_SENDER = 'Mom'
173+ share = Share(volume_id=SHARE_ID, other_visible_name=FAKE_SENDER)
174 self.fakevm.volumes[SHARE_ID] = share
175 self.listener.handle_VM_SHARE_CREATED(SHARE_ID)
176- event = self.status_frontend.aggregator.interesting_events[0]
177- self.assertIsInstance(event, aggregator.ShareAvailableStatus)
178+ self.assertEqual(
179+ 1, len(self.status_frontend.notification.notifications_shown))
180+ self.assertEqual(
181+ (aggregator.UBUNTUONE_TITLE,
182+ 'New cloud folder available: <%s> shared by <%s>' % (
183+ 'None', FAKE_SENDER), None, False),
184+ self.status_frontend.notification.notifications_shown[0])
185+ msg = self.status_frontend.messaging.messages_shown[FAKE_SENDER]
186+ # msg did not receive a time argument
187+ self.assertEqual(None, msg[1])
188+ # msg did not receive a count argument
189+ self.assertEqual(None, msg[2])
190
191 def test_new_udf_available(self):
192 """A new udf is available for subscription."""
193 udf = UDF()
194 self.listener.handle_VM_UDF_CREATED(udf)
195- event = self.status_frontend.aggregator.interesting_events[0]
196- self.assertIsInstance(event, aggregator.UDFAvailableStatus)
197+ self.assertEqual(
198+ 1, len(self.status_frontend.notification.notifications_shown))
199+ self.assertEqual(
200+ (aggregator.UBUNTUONE_TITLE, 'New cloud folder available: None',
201+ None, False),
202+ self.status_frontend.notification.notifications_shown[0])
203+ self.assertEqual(
204+ 1, len(self.status_frontend.messaging.messages_shown))
205+ self.assertEqual(
206+ 0, len(self.status_frontend.messaging.messages_updated))
207+ msg = self.status_frontend.messaging.messages_shown[
208+ aggregator.NEW_UDFS_SENDER]
209+ # msg did not receive a time argument
210+ self.assertEqual(None, msg[1])
211+ # msg did receive a count argument
212+ self.assertEqual(1, msg[2])
213+
214+ def test_two_new_udfs_available(self):
215+ """A new udf is available for subscription."""
216+ udf1 = UDF()
217+ self.listener.handle_VM_UDF_CREATED(udf1)
218+ udf2 = UDF()
219+ self.listener.handle_VM_UDF_CREATED(udf2)
220+ self.assertEqual(
221+ 2, len(self.status_frontend.notification.notifications_shown))
222+ self.assertEqual(
223+ (aggregator.UBUNTUONE_TITLE, 'New cloud folder available: None',
224+ None, False),
225+ self.status_frontend.notification.notifications_shown[0])
226+ self.assertEqual(
227+ (aggregator.UBUNTUONE_TITLE, 'New cloud folder available: None',
228+ None, False),
229+ self.status_frontend.notification.notifications_shown[1])
230+ self.assertEqual(
231+ 1, len(self.status_frontend.messaging.messages_shown))
232+ self.assertEqual(
233+ 1, len(self.status_frontend.messaging.messages_updated))
234+ msg = self.status_frontend.messaging.messages_shown[
235+ aggregator.NEW_UDFS_SENDER]
236+ # msg did not receive a time argument
237+ self.assertEqual(None, msg[1])
238+ # msg did receive a count argument
239+ self.assertEqual(1, msg[2])
240+ self.assertEqual(
241+ (aggregator.NEW_UDFS_SENDER, 1),
242+ self.status_frontend.messaging.messages_updated[
243+ aggregator.NEW_UDFS_SENDER])
244
245
246 class StatusEventTestCase(TestCase):
247-
248 """Test the status event class and children."""
249
250 CLASS = aggregator.StatusEvent
251@@ -832,7 +896,6 @@
252 self.assertEqual(self.aggregator.done_counter, 0)
253 self.assertEqual(len(self.aggregator.files_uploading), 0)
254 self.assertEqual(len(self.aggregator.files_downloading), 0)
255- self.assertEqual(len(self.aggregator.interesting_events), 0)
256
257 def assertMiscCommandQueued(self, fc):
258 """Assert that some command was queued."""
259
260=== modified file 'ubuntuone/platform/linux/messaging.py'
261--- ubuntuone/platform/linux/messaging.py 2011-02-02 16:28:49 +0000
262+++ ubuntuone/platform/linux/messaging.py 2011-02-09 13:12:13 +0000
263@@ -21,6 +21,7 @@
264 # of them are available, we should fall back to silently discarding
265 # messages.
266
267+import subprocess
268 from time import time
269
270 try:
271@@ -35,6 +36,22 @@
272 APPLICATION_NAME = 'Ubuntu One Client'
273
274
275+def hide_message(indicator):
276+ """Remove the message once it has been dealt with."""
277+ if USE_INDICATE:
278+ indicator.set_property("draw-attention", "false")
279+ indicator.hide()
280+
281+
282+# pylint: disable=W0613
283+def open_volumes(the_indicator, message_time=None):
284+ """Open the control panel to the shares tab."""
285+ subprocess.Popen(
286+ ['ubuntuone-control-panel-gtk', '--switch-to', 'volumes'])
287+ hide_message(the_indicator)
288+# pylint: enable=W0613
289+
290+
291 class Messaging(AbstractMessaging):
292 """Notification of the end user."""
293
294@@ -48,14 +65,18 @@
295 self.server.set_desktop_file(
296 "/usr/share/applications/ubuntuone-control-panel-gtk.desktop")
297
298- def show_message(self, sender, callback, message_time=None,
299+ # pylint: disable=R0913
300+ def show_message(self, sender, callback=None, message_time=None,
301 message_count=None, icon=None):
302 """Show a message in the messaging menu."""
303 if USE_INDICATE:
304- indicator = self.indicators[sender] = indicate.Indicator()
305+ indicator = indicate.Indicator()
306 indicator.set_property("subtype", "u1")
307 indicator.set_property("name", sender)
308 indicator.set_property("sender", sender)
309+
310+ if callback is None:
311+ callback = open_volumes
312 indicator.connect("user-display", callback)
313
314 if icon is not None:
315@@ -70,14 +91,10 @@
316 self.server.show()
317 indicator.show()
318 return indicator
319+ # pylint: enable=R0913
320
321- def update_count(self, sender, new_count):
322+ def update_count(self, indicator, add_count):
323 """Update the count for an existing indicator."""
324- self.indicators[sender].set_property("count", str(new_count))
325-
326-
327-def hide_message(indicator):
328- """Remove the message once it has been dealt with."""
329- if USE_INDICATE:
330- indicator.set_property("draw-attention", "false")
331- indicator.hide()
332+ if USE_INDICATE:
333+ new_count = int(indicator.get_property('count')) + add_count
334+ indicator.set_property('count', str(new_count))
335
336=== modified file 'ubuntuone/platform/windows/messaging.py'
337--- ubuntuone/platform/windows/messaging.py 2011-02-01 13:51:48 +0000
338+++ ubuntuone/platform/windows/messaging.py 2011-02-09 13:12:13 +0000
339@@ -29,16 +29,23 @@
340 class Messaging(AbstractMessaging):
341 """Notification of the end user."""
342
343- def show_message(self, sender, callback, message_time=None,
344+ # pylint: disable=R0913
345+ def show_message(self, sender, callback=None, message_time=None,
346 message_count=None, icon=None):
347 """Show a message in the messaging menu."""
348- pass
349+ # TODO: make this work
350+ # pylint: enable=R0913
351
352- def update_count(self, sender, new_count):
353+ def update_count(self, sender, add_count):
354 """Update the count for an existing indicator."""
355- pass
356-
357-
358-def hide_message(indicator):
359+ # TODO: make this work
360+
361+
362+def hide_message(indicator): # pylint: disable=W0613
363 """Remove the message once it has been dealt with."""
364- pass
365+ # TODO: make this work
366+
367+
368+def open_volumes(the_indicator, message_time=None): # pylint: disable=W0613
369+ """Open the control panel to the shares tab."""
370+ # TODO: make this work
371
372=== modified file 'ubuntuone/status/aggregator.py'
373--- ubuntuone/status/aggregator.py 2011-02-04 00:56:30 +0000
374+++ ubuntuone/status/aggregator.py 2011-02-09 13:12:13 +0000
375@@ -26,7 +26,7 @@
376
377 from ubuntuone.logger import basic_formatter, logging
378 from ubuntuone.platform.notification import Notification
379-from ubuntuone.platform.messaging import Messaging
380+from ubuntuone.platform.messaging import Messaging, open_volumes
381
382 LOG_LEVEL = logging.DEBUG
383 logger = logging.getLogger('ubuntuone.status')
384@@ -39,6 +39,7 @@
385 logger.addHandler(debug_handler)
386
387 UBUNTUONE_TITLE = "Ubuntu One"
388+NEW_UDFS_SENDER = "New Cloud Folder(s) Available"
389 FINAL_COMPLETED = "File synchronization completed."
390 FINAL_UPLOADED = "%d files were uploaded to your cloud."
391 FINAL_DOWNLOADED = "%d files were downloaded to your computer."
392@@ -181,6 +182,7 @@
393 def cleanup(self):
394 """Cleanup this instance."""
395
396+
397 class FileDiscoveryIdleState(FileDiscoveryBaseState):
398 """Waiting for first file to appear."""
399
400@@ -406,7 +408,6 @@
401 """Initialize this instance."""
402 self.clock = clock
403 self.reset()
404- self.messaging = Messaging()
405
406 def reset(self):
407 """Reset all counters and notifications."""
408@@ -418,7 +419,6 @@
409 self.upload_done = 0
410 self.files_uploading = []
411 self.files_downloading = []
412- self.interesting_events = []
413
414 if self.file_discovery_bubble:
415 self.file_discovery_bubble.cleanup()
416@@ -433,10 +433,6 @@
417 self.final_status_bubble.cleanup()
418 self.final_status_bubble = FinalStatusBubble(self)
419
420- def interesting_event(self, event):
421- """A new interesting event was found."""
422- self.interesting_events.append(event)
423-
424 def get_discovery_message(self):
425 """Get the text for the discovery bubble."""
426 lines = []
427@@ -546,20 +542,26 @@
428 self.upload_done += 1
429 self.misc_command_unqueued(command)
430
431+
432 class StatusFrontend(object):
433 """Frontend for the status aggregator, used by the StatusListener."""
434
435 def __init__(self, clock=reactor):
436 """Initialize this instance."""
437 self.aggregator = StatusAggregator(clock=clock)
438+ self.notification = Notification()
439+ self.messaging = Messaging()
440+ self.udf_message = None
441
442 def file_published(self, public_url):
443 """A file was published."""
444- self.aggregator.interesting_event(FilePublishingStatus(public_url))
445+ self.notification.send_notification(
446+ UBUNTUONE_TITLE, FilePublishingStatus(public_url).one())
447
448- def file_unpublished(self, public_url):
449+ def file_unpublished(self, public_url): # pylint: disable=W0613
450 """A file was unpublished."""
451- self.aggregator.interesting_event(FileUnpublishingStatus(public_url))
452+ self.notification.send_notification(
453+ UBUNTUONE_TITLE, FileUnpublishingStatus().one())
454
455 def download_started(self, command):
456 """A file was queued for download."""
457@@ -591,8 +593,22 @@
458
459 def new_share_available(self, share):
460 """A new share is available for subscription."""
461- self.aggregator.interesting_event(ShareAvailableStatus(share))
462+ self.messaging.show_message(share.other_visible_name)
463+ self.notification.send_notification(
464+ UBUNTUONE_TITLE, ShareAvailableStatus(share).one())
465
466 def new_udf_available(self, udf):
467 """A new udf is available for subscription."""
468- self.aggregator.interesting_event(UDFAvailableStatus(udf))
469+ if self.udf_message is not None:
470+ self.messaging.update_count(self.udf_message, 1)
471+ return
472+ self.udf_message = self.messaging.show_message(
473+ NEW_UDFS_SENDER, callback=self._reset_udf_message_callback,
474+ message_count=1)
475+ self.notification.send_notification(
476+ UBUNTUONE_TITLE, UDFAvailableStatus(udf).one())
477+
478+ def _reset_udf_message_callback(self, indicator, message_time=None):
479+ """A callback wrapper that resets the udf_message to None."""
480+ self.udf_message = None
481+ open_volumes(indicator, message_time=message_time)
482
483=== modified file 'ubuntuone/status/messaging.py'
484--- ubuntuone/status/messaging.py 2011-02-01 19:07:16 +0000
485+++ ubuntuone/status/messaging.py 2011-02-09 13:12:13 +0000
486@@ -27,11 +27,13 @@
487
488 __metaclass__ = ABCMeta
489
490+ # pylint: disable=R0913
491 @abstractmethod
492- def show_message(self, sender, callback, message_time=None,
493+ def show_message(self, sender, callback=None, message_time=None,
494 message_count=None, icon=None):
495 """Show a message in the messaging menu."""
496+ # pylint: enable=R0913
497
498 @abstractmethod
499- def update_count(self, sender, new_count):
500+ def update_count(self, sender, add_count):
501 """Update the count for an existing indicator."""

Subscribers

People subscribed via source and target branches