Merge lp:~facundo/magicicada-gui/show-md into lp:magicicada-gui

Proposed by Facundo Batista
Status: Merged
Approved by: Natalia Bidart
Approved revision: 44
Merged at revision: 47
Proposed branch: lp:~facundo/magicicada-gui/show-md
Merge into: lp:magicicada-gui
Diff against target: 348 lines (+123/-24)
4 files modified
magicicada/dbusiface.py (+30/-3)
magicicada/syncdaemon.py (+9/-0)
magicicada/tests/test_dbusiface.py (+49/-13)
magicicada/tests/test_syncdaemon.py (+35/-8)
To merge this branch: bzr merge lp:~facundo/magicicada-gui/show-md
Reviewer Review Type Date Requested Status
Natalia Bidart Approve
Review via email: mp+27406@code.launchpad.net

Description of the change

Get and deliver metadata for a given path

To post a comment you must log in.
Revision history for this message
Natalia Bidart (nataliabidart) wrote :

Docstring """Processes...""" needs fixing to """Process""". Same for "Gets" and "Returns".

review: Needs Fixing
Revision history for this message
Natalia Bidart (nataliabidart) wrote :

I was just thinking... what if the "code" for syncdaemon.get_metadata is the path per se? I think is key enough to guarantee that the metadata result is the one that the GUI/user is waiting for.

I just realized this when implementing the GUI part. Let me know what you think.

Revision history for this message
Natalia Bidart (nataliabidart) wrote :

2 more things are needed:

(a) Could you please return a python dictionary instead a dbus dictionary? I'd want to keep dbus out the GTK layer.

(b) If the path doesn't exist, we'd need a special value, not a string saying "Not a valid path". This way we can ease the future translations, and we can detect this special case in a proper way.

Revision history for this message
Facundo Batista (facundo) wrote :

After talking through IRC, what will do is:

- Will use "path" itself as the "code".

- The constant used in dbusiface.py in case of no path will be NOT_SYNCHED_PATH

- Will return a Py dict, instead a str

lp:~facundo/magicicada-gui/show-md updated
44. By Facundo Batista

Some docstring fixes and small changes.

Revision history for this message
Facundo Batista (facundo) wrote :

I just make it to return the DBus types to the GUI.

Naty does not want it, but I thought duck typing should work... even thinking that, I tried to make tests to check that the types were converted, but...

>>> isinstance(dbus.String(u'a'), unicode)
True

and

>>> isinstance(dbus.Dictionary({dbus.String('a'): dbus.String(3)}), dict)
True

So, actually, it would be too tough and too fake to assert that, and it should work rightaway.

Revision history for this message
Natalia Bidart (nataliabidart) wrote :

Nice!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'magicicada/dbusiface.py'
--- magicicada/dbusiface.py 2010-06-05 15:57:34 +0000
+++ magicicada/dbusiface.py 2010-06-14 18:14:25 +0000
@@ -50,11 +50,19 @@
50 "(Move)\(share_id=(.*?), node_id=(.*?), old_parent_id=(.*?), "50 "(Move)\(share_id=(.*?), node_id=(.*?), old_parent_id=(.*?), "
51 "new_parent_id=(.*?), new_name=(.*?)\)")51 "new_parent_id=(.*?), new_name=(.*?)\)")
5252
53# DBus exceptions store the type inside, as a string :|
54DBUSERR_NOREPLY = 'org.freedesktop.DBus.Error.NoReply'
55DBUSERR_NAMENOOWNER = 'org.freedesktop.DBus.Error.NameHasNoOwner'
56DBUSERR_PYKEYERROR = 'org.freedesktop.DBus.Python.KeyError'
57
58# some constants
59NOT_SYNCHED_PATH = "Not a valid path!"
60
5361
54def _is_retry_exception(err):62def _is_retry_exception(err):
55 """Check if the exception is a retry one."""63 """Check if the exception is a retry one."""
56 if isinstance(err, dbus.exceptions.DBusException):64 if isinstance(err, dbus.exceptions.DBusException):
57 if err.get_dbus_name() == 'org.freedesktop.DBus.Error.NoReply':65 if err.get_dbus_name() == DBUSERR_NOREPLY:
58 return True66 return True
59 return False67 return False
6068
@@ -323,8 +331,7 @@
323 try:331 try:
324 self._bus.get_name_owner('com.ubuntuone.SyncDaemon')332 self._bus.get_name_owner('com.ubuntuone.SyncDaemon')
325 except dbus.exceptions.DBusException, err:333 except dbus.exceptions.DBusException, err:
326 if err.get_dbus_name() != \334 if err.get_dbus_name() != DBUSERR_NAMENOOWNER:
327 'org.freedesktop.DBus.Error.NameHasNoOwner':
328 raise335 raise
329 started = False336 started = False
330 else:337 else:
@@ -381,3 +388,23 @@
381 d = self.sync_daemon_tool.list_shared()388 d = self.sync_daemon_tool.list_shared()
382 d.addCallback(process)389 d.addCallback(process)
383 return d390 return d
391
392 @retryable
393 def get_metadata(self, path):
394 """Return the raw metadata."""
395 logger.info("Getting metadata for %r", path)
396
397 def fix_failure(failure):
398 """Get the failure and return a nice message."""
399 if failure.check(dbus.exceptions.DBusException):
400 if failure.value.get_dbus_name() == DBUSERR_PYKEYERROR:
401 return NOT_SYNCHED_PATH
402 return failure
403
404 def process(metadata):
405 logger.debug("Got metadata for path %r: %r", path, metadata)
406 return dict(metadata)
407
408 d = self.sync_daemon_tool.get_metadata(path)
409 d.addCallbacks(process, fix_failure)
410 return d
384411
=== modified file 'magicicada/syncdaemon.py'
--- magicicada/syncdaemon.py 2010-06-11 20:09:11 +0000
+++ magicicada/syncdaemon.py 2010-06-14 18:14:25 +0000
@@ -104,6 +104,7 @@
104 self.on_folders_changed_callback = NO_OP104 self.on_folders_changed_callback = NO_OP
105 self.on_shares_to_me_changed_callback = NO_OP105 self.on_shares_to_me_changed_callback = NO_OP
106 self.on_shares_to_others_changed_callback = NO_OP106 self.on_shares_to_others_changed_callback = NO_OP
107 self.on_metadata_ready_callback = None # mandatory
107108
108 # mq needs to be polled to know progress109 # mq needs to be polled to know progress
109 self._mqcaller = None110 self._mqcaller = None
@@ -282,3 +283,11 @@
282 """Tell the SyncDaemon that the user wants it to disconnect."""283 """Tell the SyncDaemon that the user wants it to disconnect."""
283 logger.info("Telling u1.SD to disconnect")284 logger.info("Telling u1.SD to disconnect")
284 self.dbus.disconnect()285 self.dbus.disconnect()
286
287 def get_metadata(self, path):
288 """Get the metadata for given path."""
289 if self.on_metadata_ready_callback is None:
290 raise ValueError("Missing the mandatory cback for get_metadata.")
291
292 d = self.dbus.get_metadata(path)
293 d.addCallback(lambda resp: self.on_metadata_ready_callback(path, resp))
285294
=== modified file 'magicicada/tests/test_dbusiface.py'
--- magicicada/tests/test_dbusiface.py 2010-06-03 03:58:02 +0000
+++ magicicada/tests/test_dbusiface.py 2010-06-14 18:14:25 +0000
@@ -43,7 +43,7 @@
43 del self._callbacks[(dbus_interface, signal_name)]43 del self._callbacks[(dbus_interface, signal_name)]
4444
45 def get_name_owner(self, name):45 def get_name_owner(self, name):
46 """Fakes the response of the method."""46 """Fake the response of the method."""
47 assert name == 'com.ubuntuone.SyncDaemon'47 assert name == 'com.ubuntuone.SyncDaemon'
48 if isinstance(self.fake_name_owner, str):48 if isinstance(self.fake_name_owner, str):
49 return self.fake_name_owner49 return self.fake_name_owner
@@ -69,7 +69,10 @@
69 return defer.Deferred()69 return defer.Deferred()
70 methname, response = self._fake_response70 methname, response = self._fake_response
71 assert methname == name71 assert methname == name
72 return response72 if isinstance(response, Exception):
73 return defer.fail(response)
74 else:
75 return defer.succeed(response)
73 return f76 return f
7477
7578
@@ -104,9 +107,8 @@
104 return called_args107 return called_args
105108
106 def fake_sdt_response(self, method_name, response):109 def fake_sdt_response(self, method_name, response):
107 """Fakes SDT answer in deferred mode."""110 """Fake SDT answer in deferred mode."""
108 self.dbus.sync_daemon_tool._fake_response = (method_name,111 self.dbus.sync_daemon_tool._fake_response = (method_name, response)
109 defer.succeed(response))
110112
111class TestSignalHooking(SafeTests):113class TestSignalHooking(SafeTests):
112 """Signal hooking tests.114 """Signal hooking tests.
@@ -188,7 +190,7 @@
188190
189191
190class TestDataProcessingStatus(SafeTests):192class TestDataProcessingStatus(SafeTests):
191 """Processes Status before sending it to SyncDaemon."""193 """Process Status before sending it to SyncDaemon."""
192194
193 @defer.inlineCallbacks195 @defer.inlineCallbacks
194 def test_get_status(self):196 def test_get_status(self):
@@ -224,7 +226,7 @@
224226
225227
226class TestDataProcessingNameOwner(SafeTests):228class TestDataProcessingNameOwner(SafeTests):
227 """Processes Name Owner data before sending it to SyncDaemon."""229 """Process Name Owner data before sending it to SyncDaemon."""
228230
229 def test_name_owner_changed_no_syncdaemon(self):231 def test_name_owner_changed_no_syncdaemon(self):
230 """Test name owner changed callback."""232 """Test name owner changed callback."""
@@ -245,7 +247,7 @@
245247
246248
247class TestDataProcessingCQ(SafeTests):249class TestDataProcessingCQ(SafeTests):
248 """Processes CQ data before sending it to SyncDaemon."""250 """Process CQ data before sending it to SyncDaemon."""
249251
250 @defer.inlineCallbacks252 @defer.inlineCallbacks
251 def test_nodata(self):253 def test_nodata(self):
@@ -288,7 +290,7 @@
288290
289291
290class TestDataProcessingMQ(SafeTests):292class TestDataProcessingMQ(SafeTests):
291 """Processes MQ data before sending it to SyncDaemon."""293 """Process MQ data before sending it to SyncDaemon."""
292294
293 @defer.inlineCallbacks295 @defer.inlineCallbacks
294 def test_nodata(self):296 def test_nodata(self):
@@ -463,7 +465,7 @@
463465
464466
465class TestDataProcessingFolders(SafeTests):467class TestDataProcessingFolders(SafeTests):
466 """Processes Folders data before sending it to SyncDaemon."""468 """Process Folders data before sending it to SyncDaemon."""
467469
468 @defer.inlineCallbacks470 @defer.inlineCallbacks
469 def test_nodata(self):471 def test_nodata(self):
@@ -521,9 +523,29 @@
521 self.get_msd_called("on_sd_folders_changed")523 self.get_msd_called("on_sd_folders_changed")
522524
523525
526class TestDataProcessingMetadata(SafeTests):
527 """Process Metadata data before sending it to SyncDaemon."""
528
529 @defer.inlineCallbacks
530 def test_info_ok(self):
531 """Test get metadata and see response."""
532 md = dbus.Dictionary({'a': 3, 'c': 4}, signature=dbus.Signature('ss'))
533 self.fake_sdt_response('get_metadata', md)
534 rcv = yield self.dbus.get_metadata('path')
535 self.assertEqual(rcv, dict(a=3, c=4))
536
537 @defer.inlineCallbacks
538 def test_info_bad(self):
539 """Test get metadata and get the error."""
540 exc = dbus.exceptions.DBusException(
541 name='org.freedesktop.DBus.Python.KeyError')
542 self.fake_sdt_response('get_metadata', exc)
543 rcv = yield self.dbus.get_metadata('not a real path')
544 self.assertEqual(rcv, dbusiface.NOT_SYNCHED_PATH)
545
524546
525class TestDataProcessingShares(SafeTests):547class TestDataProcessingShares(SafeTests):
526 """Processes Shares data before sending it to SyncDaemon."""548 """Process Shares data before sending it to SyncDaemon."""
527549
528 @defer.inlineCallbacks550 @defer.inlineCallbacks
529 def test_sharestome_nodata(self):551 def test_sharestome_nodata(self):
@@ -720,6 +742,11 @@
720 self.dbus.get_folders()742 self.dbus.get_folders()
721 self.assertTrue(self.handler.check_inf("Getting folders"))743 self.assertTrue(self.handler.check_inf("Getting folders"))
722744
745 def test_get_metadata(self):
746 """Test call to metadata."""
747 self.dbus.get_metadata('path')
748 self.assertTrue(self.handler.check_inf("Getting metadata for u'path'"))
749
723 def test_get_shares_to_me(self):750 def test_get_shares_to_me(self):
724 """Test call to shares to me."""751 """Test call to shares to me."""
725 self.dbus.get_shares_to_me()752 self.dbus.get_shares_to_me()
@@ -847,6 +874,15 @@
847 self.assertTrue(self.handler.check_dbg(" Folders data: %r" % d))874 self.assertTrue(self.handler.check_dbg(" Folders data: %r" % d))
848875
849 @defer.inlineCallbacks876 @defer.inlineCallbacks
877 def test_metadata_processing(self):
878 """Test get metadata."""
879 d = dict(lot_of_data="I don't care")
880 self.fake_sdt_response('get_metadata', d)
881 yield self.dbus.get_metadata('path')
882 self.assertTrue(self.handler.check_dbg(
883 "Got metadata for path u'path': %r" % d))
884
885 @defer.inlineCallbacks
850 def test_sharestome_processing(self):886 def test_sharestome_processing(self):
851 """Test get shares to me with one."""887 """Test get shares to me with one."""
852 d = dict(accepted=u'True', access_level=u'View', free_bytes=u'123456',888 d = dict(accepted=u'True', access_level=u'View', free_bytes=u'123456',
@@ -877,7 +913,7 @@
877 """Test the retry decorator."""913 """Test the retry decorator."""
878914
879 class Helper(object):915 class Helper(object):
880 """Fails some times, finally succeeds."""916 """Fail some times, finally succeed."""
881 def __init__(self, limit, excep=None):917 def __init__(self, limit, excep=None):
882 self.cant = 0918 self.cant = 0
883 self.limit = limit919 self.limit = limit
@@ -915,7 +951,7 @@
915 self.assertTrue(dbusiface._is_retry_exception(err))951 self.assertTrue(dbusiface._is_retry_exception(err))
916952
917 def get_decorated_func(self, func):953 def get_decorated_func(self, func):
918 """Executes the test calling the received function."""954 """Execute the test calling the received function."""
919955
920 @dbusiface.retryable956 @dbusiface.retryable
921 def f():957 def f():
922958
=== modified file 'magicicada/tests/test_syncdaemon.py'
--- magicicada/tests/test_syncdaemon.py 2010-06-11 20:09:11 +0000
+++ magicicada/tests/test_syncdaemon.py 2010-06-14 18:14:25 +0000
@@ -133,7 +133,7 @@
133133
134 @defer.inlineCallbacks134 @defer.inlineCallbacks
135 def test_initial_value(self):135 def test_initial_value(self):
136 """Fills the status info initially."""136 """Fill the status info initially."""
137 called = []137 called = []
138 def fake():138 def fake():
139 """Fake method."""139 """Fake method."""
@@ -167,7 +167,7 @@
167 return deferred167 return deferred
168168
169 def test_status_changed_affects_cuurent_status(self):169 def test_status_changed_affects_cuurent_status(self):
170 """Makes changes to see how status are reflected."""170 """Make changes to see how status are reflected."""
171 # one set of values171 # one set of values
172 self.sd.on_sd_status_changed('name1', 'description1', False, True,172 self.sd.on_sd_status_changed('name1', 'description1', False, True,
173 False, 'queues1', 'connection1')173 False, 'queues1', 'connection1')
@@ -261,7 +261,7 @@
261261
262 @defer.inlineCallbacks262 @defer.inlineCallbacks
263 def test_initial_value(self):263 def test_initial_value(self):
264 """Fills the content queue info initially."""264 """Fill the content queue info initially."""
265 called = []265 called = []
266 self.sd.dbus.get_content_queue = lambda: called.append(True)266 self.sd.dbus.get_content_queue = lambda: called.append(True)
267 yield self.sd._get_initial_data()267 yield self.sd._get_initial_data()
@@ -341,7 +341,7 @@
341341
342 @defer.inlineCallbacks342 @defer.inlineCallbacks
343 def test_initial_value(self):343 def test_initial_value(self):
344 """Fills the meta queue info initially."""344 """Fill the meta queue info initially."""
345 called = []345 called = []
346 def f():346 def f():
347 """Helper function."""347 """Helper function."""
@@ -777,11 +777,38 @@
777 self.assertTrue(self.hdlr.check_inf("SD Name Owner changed: True"))777 self.assertTrue(self.hdlr.check_inf("SD Name Owner changed: True"))
778778
779779
780class MetadataTests(BaseTest):
781 """Get Metadata info."""
782
783 def test_get_metadata_no_callback_set(self):
784 """It's mandatory to set the callback for this response."""
785 self.assertRaises(ValueError, self.sd.get_metadata, 'path')
786
787 def test_get_metadata_ok(self):
788 """Get the metadata for given path."""
789 called = []
790 self.sd.dbus.get_metadata = lambda p: defer.succeed('foo')
791 self.sd.on_metadata_ready_callback = lambda *a: called.extend(a)
792 self.sd.get_metadata('path')
793 self.assertEqual(called, ['path', 'foo'])
794
795 def test_get_metadata_double(self):
796 """Get the metadata twice."""
797 called = []
798 fake_md = {'path1': 'foo', 'path2': 'bar'}
799 self.sd.dbus.get_metadata = lambda p: defer.succeed(fake_md[p])
800 self.sd.on_metadata_ready_callback = lambda *a: called.append(a)
801 self.sd.get_metadata('path1')
802 self.sd.get_metadata('path2')
803 self.assertEqual(called[0], ('path1', 'foo'))
804 self.assertEqual(called[1], ('path2', 'bar'))
805
806
780class FoldersTests(BaseTest):807class FoldersTests(BaseTest):
781 """Folders checking."""808 """Folders checking."""
782809
783 def test_foldercreated_callback(self):810 def test_foldercreated_callback(self):
784 """Gets the new data after the folders changed."""811 """Get the new data after the folders changed."""
785 # set the callback812 # set the callback
786 called = []813 called = []
787 self.sd.dbus.get_folders = lambda: called.append(True)814 self.sd.dbus.get_folders = lambda: called.append(True)
@@ -794,7 +821,7 @@
794821
795 @defer.inlineCallbacks822 @defer.inlineCallbacks
796 def test_initial_value(self):823 def test_initial_value(self):
797 """Fills the folder info initially."""824 """Fill the folder info initially."""
798 called = []825 called = []
799 self.sd.dbus.get_folders = lambda: called.append(True)826 self.sd.dbus.get_folders = lambda: called.append(True)
800 yield self.sd._get_initial_data()827 yield self.sd._get_initial_data()
@@ -817,7 +844,7 @@
817 """Shares checking."""844 """Shares checking."""
818845
819 def test_shares_changed_callback(self):846 def test_shares_changed_callback(self):
820 """Gets the new data after the shares changed."""847 """Get the new data after the shares changed."""
821 # set the callback848 # set the callback
822 called = []849 called = []
823 self.sd.dbus.get_shares_to_me = lambda: called.append(True)850 self.sd.dbus.get_shares_to_me = lambda: called.append(True)
@@ -831,7 +858,7 @@
831858
832 @defer.inlineCallbacks859 @defer.inlineCallbacks
833 def test_initial_value(self):860 def test_initial_value(self):
834 """Fills the folder info initially."""861 """Fill the folder info initially."""
835 called = []862 called = []
836 self.sd.dbus.get_shares_to_me = lambda: called.append(True)863 self.sd.dbus.get_shares_to_me = lambda: called.append(True)
837 self.sd.dbus.get_shares_to_others = lambda: called.append(True)864 self.sd.dbus.get_shares_to_others = lambda: called.append(True)

Subscribers

People subscribed via source and target branches