Merge lp:~nataliabidart/ubuntu/natty/ubuntuone-control-panel/ubuntuone-control-panel-0.9.6 into lp:ubuntu/natty/ubuntuone-control-panel

Proposed by Natalia Bidart
Status: Merged
Merged at revision: 21
Proposed branch: lp:~nataliabidart/ubuntu/natty/ubuntuone-control-panel/ubuntuone-control-panel-0.9.6
Merge into: lp:ubuntu/natty/ubuntuone-control-panel
Diff against target: 590 lines (+250/-37)
12 files modified
PKG-INFO (+1/-1)
debian/changelog (+20/-0)
debian/control (+6/-6)
setup.py (+1/-1)
ubuntuone/controlpanel/backend.py (+25/-8)
ubuntuone/controlpanel/gtk/gui.py (+24/-6)
ubuntuone/controlpanel/gtk/tests/__init__.py (+11/-2)
ubuntuone/controlpanel/gtk/tests/test_gui.py (+61/-1)
ubuntuone/controlpanel/gtk/tests/test_gui_basic.py (+1/-1)
ubuntuone/controlpanel/gtk/tests/test_widgets.py (+8/-0)
ubuntuone/controlpanel/gtk/widgets.py (+2/-0)
ubuntuone/controlpanel/tests/test_backend.py (+90/-11)
To merge this branch: bzr merge lp:~nataliabidart/ubuntu/natty/ubuntuone-control-panel/ubuntuone-control-panel-0.9.6
Reviewer Review Type Date Requested Status
Ubuntu Sponsors Team Pending
Review via email: mp+57347@code.launchpad.net

Description of the change

  * New upstream release.
    [ Natalia B. Bidart <email address hidden> ]
      - Free bytes will not be displayed in the UI for read-only shares.
      Also, backend now handles quota info not available for the root folder
      (LP: #726580).
      - Setting the unity's urgent prop only if available (LP: #755185).
      - Made panel title selectable. Tab messages are now also selectable
      (LP: #757543).
      - Highlight with red and bold when free space available is very little
      (either in own volumes or shares) (LP: #753989).

  * debian/control:
    - bump depends versions for ubuntuone-client (>= 1.6.0) and
    ubuntu-sso-client (>= 1.2.0).

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'PKG-INFO'
2--- PKG-INFO 2011-04-08 16:07:22 +0000
3+++ PKG-INFO 2011-04-12 16:04:35 +0000
4@@ -1,6 +1,6 @@
5 Metadata-Version: 1.1
6 Name: ubuntuone-control-panel
7-Version: 0.9.5
8+Version: 0.9.6
9 Summary: Ubuntu One Control Panel
10 Home-page: https://launchpad.net/ubuntuone-control-panel
11 Author: Natalia Bidart
12
13=== modified file 'debian/changelog'
14--- debian/changelog 2011-04-08 20:23:32 +0000
15+++ debian/changelog 2011-04-12 16:04:35 +0000
16@@ -1,3 +1,23 @@
17+ubuntuone-control-panel (0.9.6-0ubuntu1) UNRELEASED; urgency=low
18+
19+ * New upstream release.
20+
21+ [ Natalia B. Bidart <natalia.bidart@canonical.com> ]
22+ - Free bytes will not be displayed in the UI for read-only shares.
23+ Also, backend now handles quota info not available for the root folder
24+ (LP: #726580).
25+ - Setting the unity's urgent prop only if available (LP: #755185).
26+ - Made panel title selectable. Tab messages are now also selectable
27+ (LP: #757543).
28+ - Highlight with red and bold when free space available is very little
29+ (either in own volumes or shares) (LP: #753989).
30+
31+ * debian/control:
32+ - bump depends versions for ubuntuone-client (>= 1.6.0) and
33+ ubuntu-sso-client (>= 1.2.0).
34+
35+ -- Natalia Bidart (nessita) <nataliabidart@gmail.com> Tue, 12 Apr 2011 12:11:11 -0300
36+
37 ubuntuone-control-panel (0.9.5-0ubuntu1) natty; urgency=low
38
39 * New upstream release:
40
41=== modified file 'debian/control'
42--- debian/control 2011-03-10 03:09:16 +0000
43+++ debian/control 2011-04-12 16:04:35 +0000
44@@ -17,7 +17,7 @@
45 ${python:Depends},
46 python,
47 python-ubuntuone-control-panel (= ${binary:Version}),
48- ubuntuone-client (>= 1.5.6),
49+ ubuntuone-client (>= 1.6.0),
50 Recommends: ubuntuone-control-panel-gui
51 Description: Ubuntu One Control Panel
52 Desktop application to manage a Ubuntu One account.
53@@ -37,8 +37,8 @@
54 python-simplejson,
55 python-twisted-core,
56 python-twisted-web,
57- python-ubuntuone-client (>= 1.5.6),
58- ubuntu-sso-client (>= 1.1.11),
59+ python-ubuntuone-client (>= 1.6.0),
60+ ubuntu-sso-client (>= 1.2.0),
61 Description: Ubuntu One Control Panel Python Libraries
62 Ubuntu One Control Panel provides a Python library to manage an Ubuntu One
63 account.
64@@ -54,9 +54,9 @@
65 python-defer,
66 python-gobject,
67 python-gtk2,
68- python-ubuntuone-client (>= 1.5.6),
69- ubuntu-sso-client (>= 1.1.11),
70- ubuntuone-client (>= 1.5.6),
71+ python-ubuntuone-client (>= 1.6.0),
72+ ubuntu-sso-client (>= 1.2.0),
73+ ubuntuone-client (>= 1.6.0),
74 ubuntuone-control-panel (= ${binary:Version}),
75 Provides: ubuntuone-control-panel-gui
76 Description: Ubuntu One Control Panel
77
78=== modified file 'setup.py'
79--- setup.py 2011-04-08 16:07:22 +0000
80+++ setup.py 2011-04-12 16:04:35 +0000
81@@ -79,7 +79,7 @@
82
83 DistUtilsExtra.auto.setup(
84 name='ubuntuone-control-panel',
85- version='0.9.5',
86+ version='0.9.6',
87 license='GPL v3',
88 author='Natalia Bidart',
89 author_email='natalia.bidart@canonical.com',
90
91=== modified file 'ubuntuone/controlpanel/backend.py'
92--- ubuntuone/controlpanel/backend.py 2011-04-08 16:07:22 +0000
93+++ ubuntuone/controlpanel/backend.py 2011-04-12 16:04:35 +0000
94@@ -100,6 +100,7 @@
95 FOLDER_TYPE = u'UDF'
96 SHARE_TYPE = u'SHARE'
97 NAME_NOT_SET = u'ENAMENOTSET'
98+ FREE_BYTES_NOT_AVAILABLE = u'EFREEBYTESNOTAVAILABLE'
99 STATUS_DISABLED = {MSG_KEY: '', STATUS_KEY: FILE_SYNC_DISABLED}
100
101 def __init__(self, shutdown_func=None):
102@@ -450,14 +451,21 @@
103 """Get the volumes info."""
104 self._volumes = {}
105
106- account = yield self.account_info()
107+ try:
108+ account = yield self.account_info()
109+ except Exception: # pylint: disable=W0703
110+ logger.exception('volumes_info: quota could not be retrieved:')
111+ free_bytes = self.FREE_BYTES_NOT_AVAILABLE
112+ else:
113+ free_bytes = int(account['quota_total']) - \
114+ int(account['quota_used'])
115+
116 root_dir = yield dbus_client.get_root_dir()
117 shares_dir = yield dbus_client.get_shares_dir()
118 shares_dir_link = yield dbus_client.get_shares_dir_link()
119 folders = yield dbus_client.get_folders()
120 shares = yield dbus_client.get_shares()
121
122- free_bytes = int(account['quota_total']) - int(account['quota_used'])
123 root_volume = {u'volume_id': u'', u'path': root_dir,
124 u'subscribed': 'True', u'type': self.ROOT_TYPE}
125 self._volumes[u''] = root_volume
126@@ -465,15 +473,17 @@
127 # group shares by the offering user
128 shares_result = defaultdict(list)
129 for share in shares:
130+ if not bool(share['accepted']):
131+ continue
132+
133 share[u'type'] = self.SHARE_TYPE
134
135 vid = share['volume_id']
136- assert vid not in self._volumes
137+ if vid in self._volumes:
138+ logger.warning('volumes_info: share %r already in the volumes '
139+ 'list (%r).', vid, self._volumes[vid])
140 self._volumes[vid] = share
141
142- if not bool(share['accepted']):
143- continue
144-
145 nicer_path = share[u'path'].replace(shares_dir, shares_dir_link)
146 share[u'path'] = nicer_path
147
148@@ -488,13 +498,20 @@
149 folder[u'type'] = self.FOLDER_TYPE
150
151 vid = folder['volume_id']
152- assert vid not in self._volumes
153+ if vid in self._volumes:
154+ logger.warning('volumes_info: udf %r already in the volumes '
155+ 'list (%r).', vid, self._volumes[vid])
156 self._volumes[vid] = folder
157
158 result = [(u'', unicode(free_bytes), [root_volume] + folders)]
159
160 for other_username, shares in shares_result.iteritems():
161- result.append((other_username, shares[0][u'free_bytes'], shares))
162+ send_freebytes = any(s['access_level'] == 'Modify' for s in shares)
163+ if send_freebytes:
164+ free_bytes = shares[0][u'free_bytes']
165+ else:
166+ free_bytes = self.FREE_BYTES_NOT_AVAILABLE
167+ result.append((other_username, free_bytes, shares))
168
169 returnValue(result)
170
171
172=== modified file 'ubuntuone/controlpanel/gtk/gui.py'
173--- ubuntuone/controlpanel/gtk/gui.py 2011-04-08 16:07:22 +0000
174+++ ubuntuone/controlpanel/gtk/gui.py 2011-04-12 16:04:35 +0000
175@@ -456,7 +456,7 @@
176 'this computer')
177 MY_FOLDERS = _('My folders')
178 ALWAYS_SUBSCRIBED = _('Always in sync!')
179- FREE_SPACE = _('%(free_space)s available storage')
180+ FREE_SPACE_TEXT = _('%(free_space)s available storage')
181 NO_VOLUMES = _('No folders to show.')
182 NAME_NOT_SET = _('[unknown user name]')
183 CONFIRM_MERGE = _('The contents of your cloud folder will be merged with '
184@@ -466,13 +466,15 @@
185 MUSIC_REAL_PATH = '~/.ubuntuone/Purchased from Ubuntu One'
186
187 MAX_COLS = 8
188+ MIN_SIZE_FULL = 1048576
189
190 CONTACT_ICON_NAME = 'avatar-default'
191 FOLDER_ICON_NAME = 'folder'
192 SHARE_ICON_NAME = 'folder-remote'
193 MUSIC_ICON_NAME = 'audio-x-generic'
194- ROW_HEADER = '<span font_size="large"><b>%s</b></span> ' \
195- '<span foreground="grey">%s</span>'
196+ FREE_SPACE = '<span foreground="grey">%s</span>' % FREE_SPACE_TEXT
197+ NO_FREE_SPACE = '<span foreground="red"><b>%s</b></span>' % FREE_SPACE_TEXT
198+ ROW_HEADER = '<span font_size="large"><b>%s</b></span> %s'
199 ROOT = '%s - <span foreground="%s" font_size="small">%s</span>'
200
201 def __init__(self, main_window=None):
202@@ -534,12 +536,28 @@
203 else:
204 name = self.MY_FOLDERS
205
206- free_bytes_args = {'free_space': self.humanize(int(free_bytes))}
207- row = (self.ROW_HEADER % (name, self.FREE_SPACE % free_bytes_args),
208+ scroll_to_cell = False
209+ if free_bytes == backend.ControlBackend.FREE_BYTES_NOT_AVAILABLE:
210+ free_bytes = ''
211+ else:
212+ free_bytes = int(free_bytes)
213+ if free_bytes < self.MIN_SIZE_FULL:
214+ free_bytes_str = self.NO_FREE_SPACE
215+ scroll_to_cell = True
216+ else:
217+ free_bytes_str = self.FREE_SPACE
218+ free_bytes_args = {'free_space': self.humanize(free_bytes)}
219+ free_bytes = free_bytes_str % free_bytes_args
220+
221+ row = (self.ROW_HEADER % (name, free_bytes),
222 True, self.CONTACT_ICON_NAME, False, False,
223 gtk.ICON_SIZE_LARGE_TOOLBAR, None, None)
224 treeiter = self.volumes_store.append(None, row)
225
226+ if scroll_to_cell:
227+ path = self.volumes_store.get_string_from_iter(treeiter)
228+ self.volumes_view.scroll_to_cell(path)
229+
230 volumes.sort(key=operator.itemgetter('path'))
231 for volume in volumes:
232 sensitive = True
233@@ -1722,7 +1740,7 @@
234 if not USE_LIBUNITY:
235 return
236 entry = Unity.LauncherEntry.get_for_desktop_id(U1_DOTDESKTOP)
237- if entry.props.urgent:
238+ if getattr(entry.props, 'urgent', False):
239 self.switch_to('volumes')
240 entry.props.urgent = False
241
242
243=== modified file 'ubuntuone/controlpanel/gtk/tests/__init__.py'
244--- ubuntuone/controlpanel/gtk/tests/__init__.py 2011-04-08 16:07:22 +0000
245+++ ubuntuone/controlpanel/gtk/tests/__init__.py 2011-04-12 16:04:35 +0000
246@@ -68,7 +68,6 @@
247 {u'volume_id': u'1234', u'name': u'do',
248 u'path': u'/home/tester/.local/share/ubuntuone/shares/do from Other User',
249 u'subscribed': u'', u'type': ControlBackend.SHARE_TYPE},
250-
251 {u'volume_id': u'5678', u'name': u're',
252 u'path': u'/home/tester/.local/share/ubuntuone/shares/re from Other User',
253 u'subscribed': u'True', u'type': ControlBackend.SHARE_TYPE},
254@@ -76,7 +75,17 @@
255
256 FAKE_VOLUMES_INFO = [
257 (u'', u'147852369', [ROOT] + FAKE_FOLDERS_INFO),
258- (u'Other User', u'985674', FAKE_SHARES_INFO),
259+ (u'Other User', gui.VolumesPanel.MIN_SIZE_FULL, FAKE_SHARES_INFO),
260+]
261+
262+FAKE_VOLUMES_NO_FREE_SPACE_INFO = [
263+ (u'', u'500', [ROOT]),
264+ (u'No free space', u'0',
265+ [{u'volume_id': u'0', u'name': u'full', u'path': u'full-share',
266+ u'subscribed': u'', u'type': ControlBackend.SHARE_TYPE}]),
267+ (u'Almost no free space', gui.VolumesPanel.MIN_SIZE_FULL - 1,
268+ [{u'volume_id': u'1', u'name': u'almostfull', u'path': u'almost-full',
269+ u'subscribed': u'', u'type': ControlBackend.SHARE_TYPE}]),
270 ]
271
272 FAKE_DEVICE_INFO = {
273
274=== modified file 'ubuntuone/controlpanel/gtk/tests/test_gui.py'
275--- ubuntuone/controlpanel/gtk/tests/test_gui.py 2011-04-08 16:07:22 +0000
276+++ ubuntuone/controlpanel/gtk/tests/test_gui.py 2011-04-12 16:04:35 +0000
277@@ -23,7 +23,7 @@
278 from ubuntuone.controlpanel.gtk import gui
279 from ubuntuone.controlpanel.gtk.tests import (FAKE_ACCOUNT_INFO,
280 FAKE_DEVICE_INFO, FAKE_DEVICES_INFO, FAKE_FOLDERS_INFO,
281- FAKE_VOLUMES_INFO, FAKE_REPLICATIONS_INFO,
282+ FAKE_VOLUMES_INFO, FAKE_VOLUMES_NO_FREE_SPACE_INFO, FAKE_REPLICATIONS_INFO,
283 MUSIC_FOLDER, ROOT, USER_HOME,
284 FakedConfirmDialog,
285 )
286@@ -260,6 +260,66 @@
287
288 self.assertEqual(len(self.ui.volumes_store), 0)
289
290+ def test_on_volumes_info_ready_highlights_little_free_space(self):
291+ """The free space is red if is zero (or close to 0)."""
292+ self.ui.on_volumes_info_ready(FAKE_VOLUMES_NO_FREE_SPACE_INFO)
293+
294+ treeiter = self.ui.volumes_store.get_iter_root()
295+ for name, free_bytes, volumes in FAKE_VOLUMES_NO_FREE_SPACE_INFO:
296+ name = "%s's" % name if name else self.ui.MY_FOLDERS
297+ free_bytes = self.ui.humanize(int(free_bytes))
298+ free_bytes = self.ui.NO_FREE_SPACE % {'free_space': free_bytes}
299+
300+ # check parent row
301+ row = self.ui.volumes_store.get(treeiter,
302+ *xrange(self.ui.MAX_COLS))
303+
304+ self.assertEqual(row[0], self.ui.ROW_HEADER % (name, free_bytes))
305+
306+ treeiter = self.ui.volumes_store.iter_next(treeiter)
307+
308+ if treeiter is not None:
309+ # skip the empty row
310+ row = self.ui.volumes_store.get(treeiter,
311+ *xrange(self.ui.MAX_COLS))
312+ self.assertEqual(row, self.ui._empty_row)
313+
314+ # grab next non-empty row
315+ treeiter = self.ui.volumes_store.iter_next(treeiter)
316+
317+ def test_on_volumes_info_ready_handles_no_quota_info(self):
318+ """The lack of free space is handled."""
319+ info = [
320+ (u'', gui.backend.ControlBackend.FREE_BYTES_NOT_AVAILABLE, [ROOT]),
321+ (u'No free space available',
322+ gui.backend.ControlBackend.FREE_BYTES_NOT_AVAILABLE,
323+ [{u'volume_id': u'0', u'name': u'full',
324+ u'path': u'full-share', u'subscribed': u'',
325+ u'type': gui.backend.ControlBackend.SHARE_TYPE}]),
326+ ]
327+ self.ui.on_volumes_info_ready(info)
328+
329+ treeiter = self.ui.volumes_store.get_iter_root()
330+ for name, free_bytes, volumes in info:
331+ name = "%s's" % name if name else self.ui.MY_FOLDERS
332+
333+ # check parent row
334+ row = self.ui.volumes_store.get(treeiter,
335+ *xrange(self.ui.MAX_COLS))
336+
337+ self.assertEqual(row[0], self.ui.ROW_HEADER % (name, ''))
338+
339+ treeiter = self.ui.volumes_store.iter_next(treeiter)
340+
341+ if treeiter is not None:
342+ # skip the empty row
343+ row = self.ui.volumes_store.get(treeiter,
344+ *xrange(self.ui.MAX_COLS))
345+ self.assertEqual(row, self.ui._empty_row)
346+
347+ # grab next non-empty row
348+ treeiter = self.ui.volumes_store.iter_next(treeiter)
349+
350 def test_on_volumes_info_error(self):
351 """The volumes info couldn't be retrieved."""
352 self.ui.on_volumes_info_error()
353
354=== modified file 'ubuntuone/controlpanel/gtk/tests/test_gui_basic.py'
355--- ubuntuone/controlpanel/gtk/tests/test_gui_basic.py 2011-04-08 16:07:22 +0000
356+++ ubuntuone/controlpanel/gtk/tests/test_gui_basic.py 2011-04-12 16:04:35 +0000
357@@ -143,7 +143,7 @@
358 THE_FLEP.urgent = True
359 self.patch(gui.Unity, "LauncherEntry", FakeLauncherEntry)
360 cp = gui.ControlPanelWindow()
361- cp.emit('focus-in-event', None)
362+ cp.emit('focus-in-event', gui.gtk.gdk.Event(gui.gtk.gdk.FOCUS_CHANGE))
363 self.assertEqual(
364 False, THE_FLEP.urgent, 'remove_urgency should have been called.')
365
366
367=== modified file 'ubuntuone/controlpanel/gtk/tests/test_widgets.py'
368--- ubuntuone/controlpanel/gtk/tests/test_widgets.py 2011-03-23 16:06:41 +0000
369+++ ubuntuone/controlpanel/gtk/tests/test_widgets.py 2011-04-12 16:04:35 +0000
370@@ -148,6 +148,10 @@
371 actual = widget.loading.spinner.style.fg[widgets.gtk.STATE_NORMAL]
372 self.assertEqual(actual, widgets.gtk.gdk.Color(expected))
373
374+ def test_selectable(self):
375+ """The widget is selectable."""
376+ self.assertTrue(self.widget.label.get_selectable())
377+
378
379 class PanelTitleTestCase(TestCase):
380 """Tets case for a special title for each management panel."""
381@@ -186,3 +190,7 @@
382 """The label padding is correct."""
383 self.assertEqual(self.widget.get_padding(),
384 widgets.DEFAULT_PADDING)
385+
386+ def test_selectable(self):
387+ """The widget is selectable."""
388+ self.assertTrue(self.widget.get_selectable())
389
390=== modified file 'ubuntuone/controlpanel/gtk/widgets.py'
391--- ubuntuone/controlpanel/gtk/widgets.py 2011-03-23 16:06:41 +0000
392+++ ubuntuone/controlpanel/gtk/widgets.py 2011-04-12 16:04:35 +0000
393@@ -55,6 +55,7 @@
394 self.loading = Loading(loading_label, fg_color=fg_color)
395
396 self.label = gtk.Label()
397+ self.label.set_selectable(True)
398 self.label.show()
399 if fg_color is not None:
400 self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.Color(fg_color))
401@@ -113,6 +114,7 @@
402 self.set_property('xalign', 0.0)
403 self.set_line_wrap(True)
404 self.set_line_wrap_mode(pango.WRAP_WORD)
405+ self.set_selectable(True)
406 self.show_all()
407
408
409
410=== modified file 'ubuntuone/controlpanel/tests/test_backend.py'
411--- ubuntuone/controlpanel/tests/test_backend.py 2011-04-08 16:07:22 +0000
412+++ ubuntuone/controlpanel/tests/test_backend.py 2011-04-12 16:04:35 +0000
413@@ -24,7 +24,7 @@
414 import simplejson
415
416 from twisted.internet import defer
417-from twisted.internet.defer import inlineCallbacks
418+from twisted.internet.defer import inlineCallbacks, returnValue
419 from ubuntuone.devtools.handlers import MementoHandler
420
421 from ubuntuone.controlpanel import backend, replication_client
422@@ -98,6 +98,8 @@
423 subscribed_folders = []
424 subscribed_shares = []
425 actions = []
426+ shares = []
427+ folders = []
428
429 def get_credentials(self):
430 """Return the mock credentials."""
431@@ -179,7 +181,7 @@
432
433 def get_folders(self):
434 """Grab list of folders."""
435- return SAMPLE_FOLDERS
436+ return MockDBusClient.folders
437
438 def subscribe_folder(self, volume_id):
439 """Subcribe to 'volume_id'."""
440@@ -191,7 +193,7 @@
441
442 def get_shares(self):
443 """Grab list of shares."""
444- return SAMPLE_SHARES
445+ return MockDBusClient.shares
446
447 def subscribe_share(self, volume_id):
448 """Subcribe to 'volume_id'."""
449@@ -563,10 +565,14 @@
450 self.be.wc.results[QUOTA_API] = SAMPLE_QUOTA_JSON
451
452 @inlineCallbacks
453- def test_volumes_info(self):
454- """The volumes_info method exercises its callback."""
455- result = yield self.be.account_info()
456- free_bytes = int(result['quota_total']) - int(result['quota_used'])
457+ def expected_volumes(self, sample_shares, sample_folders):
458+ """Get shares and group by sharing user, get folders and free space."""
459+ try:
460+ result = yield self.be.account_info()
461+ except Exception: # pylint: disable=W0703
462+ free_bytes = self.be.FREE_BYTES_NOT_AVAILABLE
463+ else:
464+ free_bytes = int(result['quota_total']) - int(result['quota_used'])
465
466 # get root dir info
467 root_volume = {u'volume_id': u'', u'path': ROOT_PATH,
468@@ -574,7 +580,7 @@
469
470 # get shares and group by sharing user
471 shares = defaultdict(list)
472- for share in SAMPLE_SHARES:
473+ for share in sample_shares:
474 # filter out non accepted values
475 if not bool(share['accepted']):
476 continue
477@@ -593,15 +599,29 @@
478 shares[username].append(share)
479
480 folders = []
481- for folder in SAMPLE_FOLDERS:
482+ for folder in sample_folders:
483 folder = folder.copy()
484 folder[u'type'] = self.be.FOLDER_TYPE
485 folders.append(folder)
486
487 expected = [(u'', unicode(free_bytes), [root_volume] + folders)]
488 for other_user, data in shares.iteritems():
489- expected.append((other_user, data[0][u'free_bytes'], data))
490-
491+ send_freebytes = any(d['access_level'] == 'Modify' for d in data)
492+ if send_freebytes:
493+ free_bytes = data[0][u'free_bytes']
494+ else:
495+ free_bytes = self.be.FREE_BYTES_NOT_AVAILABLE
496+ expected.append((other_user, free_bytes, data))
497+
498+ returnValue(expected)
499+
500+ @inlineCallbacks
501+ def test_volumes_info(self):
502+ """The volumes_info method exercises its callback."""
503+ self.patch(MockDBusClient, 'shares', SAMPLE_SHARES)
504+ self.patch(MockDBusClient, 'folders', SAMPLE_FOLDERS)
505+
506+ expected = yield self.expected_volumes(SAMPLE_SHARES, SAMPLE_FOLDERS)
507 result = yield self.be.volumes_info()
508 self.assertEqual(result, expected)
509
510@@ -614,14 +634,23 @@
511 @inlineCallbacks
512 def test_volumes_are_cached(self):
513 """The volume list is cached."""
514+ self.patch(MockDBusClient, 'shares', SAMPLE_SHARES)
515+ self.patch(MockDBusClient, 'folders', SAMPLE_FOLDERS)
516+
517 # get root dir info
518 root_volume = {u'volume_id': u'', u'path': ROOT_PATH,
519 u'subscribed': 'True', u'type': self.be.ROOT_TYPE}
520 expected = {u'': root_volume}
521 for volume in SAMPLE_SHARES + SAMPLE_FOLDERS:
522+ volume = volume.copy()
523 if volume[u'type'] == u'UDF':
524 volume[u'type'] = self.be.FOLDER_TYPE
525 else:
526+ if not bool(volume[u'accepted']):
527+ continue
528+ path = volume[u'path']
529+ nicer_path = path.replace(SHARES_PATH, SHARES_PATH_LINK)
530+ volume[u'path'] = nicer_path
531 volume[u'type'] = self.be.SHARE_TYPE
532
533 sid = volume['volume_id']
534@@ -639,6 +668,56 @@
535 yield self.test_volumes_are_cached()
536
537 @inlineCallbacks
538+ def test_volumes_info_no_quota_for_read_onlys(self):
539+ """The volumes_info does not send qupota info for RO shares."""
540+ read_only_shares = [
541+ {u'accepted': u'True',
542+ u'subscribed': u'True',
543+ u'access_level': u'View',
544+ u'free_bytes': u'39892622746',
545+ u'generation': u'2704',
546+ u'name': u're',
547+ u'node_id': u'c483f419-ed28-490a-825d-a8c074e2d795',
548+ u'other_username': u'otheruser',
549+ u'other_visible_name': u'Other User',
550+ u'path': SHARES_PATH + u'/re from Other User',
551+ u'type': u'Share',
552+ u'volume_id': u'4a1b263b-a2b3-4f66-9e66-4cd18050810d'},
553+ {u'accepted': u'True',
554+ u'subscribed': u'True',
555+ u'access_level': u'View',
556+ u'free_bytes': u'39892622746',
557+ u'generation': u'2704',
558+ u'name': u'do',
559+ u'node_id': u'84544ea4-aefe-4f91-9bb9-ed7b0a805baf',
560+ u'other_username': u'otheruser',
561+ u'other_visible_name': u'Other User',
562+ u'path': SHARES_PATH + u'/do from Other User',
563+ u'type': u'Share',
564+ u'volume_id': u'7d130dfe-98b2-4bd5-8708-9eeba9838ac0'},
565+ ]
566+
567+ self.patch(MockDBusClient, 'shares', read_only_shares)
568+ self.patch(MockDBusClient, 'folders', SAMPLE_FOLDERS)
569+
570+ expected = yield self.expected_volumes(read_only_shares,
571+ SAMPLE_FOLDERS)
572+ result = yield self.be.volumes_info()
573+ self.assertEqual(result, expected)
574+
575+ @inlineCallbacks
576+ def test_volumes_info_no_quota_for_root(self):
577+ """The volumes_info returns info even if quota call fails."""
578+ # pylint: disable=E1101
579+ self.be.wc.failure = 500
580+ self.patch(MockDBusClient, 'shares', SAMPLE_SHARES)
581+ self.patch(MockDBusClient, 'folders', SAMPLE_FOLDERS)
582+
583+ expected = yield self.expected_volumes(SAMPLE_SHARES, SAMPLE_FOLDERS)
584+ result = yield self.be.volumes_info()
585+ self.assertEqual(result, expected)
586+
587+ @inlineCallbacks
588 def test_subscribe_volume_folder(self):
589 """The subscribe_volume method subscribes a folder."""
590 fid = '0123-4567'

Subscribers

People subscribed via source and target branches