Merge lp:~diegosarmentero/ubuntuone-control-panel/folder-show-garbage into lp:ubuntuone-control-panel

Proposed by Diego Sarmentero on 2012-01-18
Status: Merged
Approved by: Diego Sarmentero on 2012-01-26
Approved revision: 251
Merged at revision: 254
Proposed branch: lp:~diegosarmentero/ubuntuone-control-panel/folder-show-garbage
Merge into: lp:ubuntuone-control-panel
Diff against target: 240 lines (+65/-17)
7 files modified
ubuntuone/controlpanel/backend.py (+16/-6)
ubuntuone/controlpanel/gui/qt/addfolder.py (+3/-5)
ubuntuone/controlpanel/gui/qt/tests/__init__.py (+4/-0)
ubuntuone/controlpanel/gui/qt/tests/test_addfolder.py (+2/-1)
ubuntuone/controlpanel/sd_client/__init__.py (+4/-0)
ubuntuone/controlpanel/tests/test_backend.py (+28/-2)
ubuntuone/controlpanel/tests/test_sd_client.py (+8/-3)
To merge this branch: bzr merge lp:~diegosarmentero/ubuntuone-control-panel/folder-show-garbage
Reviewer Review Type Date Requested Status
Natalia Bidart 2012-01-18 Approve on 2012-01-26
Roberto Alsina (community) Approve on 2012-01-25
Review via email: mp+89094@code.launchpad.net

Commit Message

Fixed: QT UI: Folder list may show garbage for user homes non-ascii (LP: #851356).

Description of the Change

To test it IRL you will need to have a windows user with unicode chars in the username and be able to open the control panel and see the Ubuntu One folder.

To post a comment you must log in.
247. By Diego Sarmentero on 2012-01-18

get_home_dir modified

Roberto Alsina (ralsina) wrote :

I just don't understand how get_home_dir is supposed to work. It will set self.home_dir in some eventual future, so after calling get_home_dir, thereisno guarantee self.home_dir will have anything useful.

I think that should be blocking code, and not return until self.home_dir is set.

Unless of course, I missed something...

review: Needs Information
248. By Diego Sarmentero on 2012-01-19

removing unnecessary self.home_dir

Natalia Bidart (nataliabidart) wrote :

The branch looks good. There are a couple of this that confuse me:

* you're mixing unicode and non unicode in 200 to 202. Now it works because there is automatic promotion to unicode, but we should avoid that and be explicit.

* when trying to create a UDF using u1client trunk and this branch, the creation fails and the syncdaemon log shows:

2012-01-19 11:00:45,206 - ubuntuone.SyncDaemon.VM - DEBUG - create udf: 'C:\\Users\\\xe5\x8d\x97\xe6\xb8\xa1\xe6\xb1\x9f \xd7\xa0\xd7\x95\xd7\xa0\xd7\x95\\Links'
C:\Python27\lib\genericpath.py:71: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal
  s1 = min(m)

2012-01-19 11:00:45,207 - ubuntuone.SyncDaemon.EQ - DEBUG - push_event: VM_UDF_CREATE_ERROR, kwargs: {'path': 'C:\\Users\\\xe5\x8d\x97\xe6\xb8\xa1\xe6\xb1\x9f \xd7\xa0\xd7\x95\xd7\xa0\xd7\x95\\Links', 'error': "INVALID_PATH: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)"}

2012-01-19 11:00:45,207 - ubuntuone.SyncDaemon.InteractionInterfaces - DEBUG - handle_VM_UDF_CREATE_ERROR: args (<ubuntuone.syncdaemon.interaction_interfaces.SyncdaemonEventListener object at 0x033AFED0>,), kwargs {'path': 'C:\\Users\\\xe5\x8d\x97\xe6\xb8\xa1\xe6\xb1\x9f \xd7\xa0\xd7\x95\xd7\xa0\xd7\x95\\Links', 'error
': "INVALID_PATH: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)"}.

Would you please confirm if the problem is in syncdaemon's end or controlpanel's end?

review: Needs Fixing
Natalia Bidart (nataliabidart) wrote :

Let me know if this branch is meant to only solve the showing of the folders, and I'll make a new bug report and change the voting.

249. By Diego Sarmentero on 2012-01-23

merge

250. By Diego Sarmentero on 2012-01-25

_process_path improved

Diego Sarmentero (diegosarmentero) wrote :

> Let me know if this branch is meant to only solve the showing of the folders,
> and I'll make a new bug report and change the voting.

This is a Ubuntu One Client issue, I already create a bug for it and i'm working on that:
https://bugs.launchpad.net/ubuntuone-client/+bug/921703

Roberto Alsina (ralsina) wrote :

+1

review: Approve
Natalia Bidart (nataliabidart) wrote :

- Seems like the import of USER_HOME was moved in ubuntuone/controlpanel/tests/test_backend.py and now is the imports are not alphabetically ordered.

- While this test_volumes_info_process_path is a great adding, the assertion self.assertTrue(USER_HOME in display_name) is a bit weak. Can you please change that for:

prefix = 'My Ubuntu' + USER_HOME
self.assertTrue(display_name.startswith(prefix))

- Tests in windows are not padding for me, but neither are the suite from trunk, so seems unrelated.

I'm approving but please fix the first two items before landing.

review: Approve
251. By Diego Sarmentero on 2012-01-26

Tests improved.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ubuntuone/controlpanel/backend.py'
2--- ubuntuone/controlpanel/backend.py 2011-09-16 16:38:43 +0000
3+++ ubuntuone/controlpanel/backend.py 2012-01-26 12:48:23 +0000
4@@ -139,6 +139,10 @@
5
6 logger.info('ControlBackend: instance started.')
7
8+ def get_home_dir(self):
9+ """Return a defer with the home_dir from ubuntu one client."""
10+ return self.sd_client.get_home_dir()
11+
12 def _process_file_sync_status(self, status):
13 """Process raw file sync status into custom format.
14
15@@ -289,11 +293,15 @@
16
17 returnValue(local_device)
18
19+ @inlineCallbacks
20 def _process_path(self, path):
21 """Trim 'path' so the '~' is removed."""
22- home = os.path.expanduser('~')
23- result = path.replace(os.path.join(home, ''), '')
24- return result
25+ home_dir = yield self.get_home_dir()
26+ if not home_dir.endswith(os.path.sep):
27+ home_dir += os.path.sep
28+ if path.startswith(home_dir):
29+ path = path[len(home_dir):]
30+ returnValue(path)
31
32 @inlineCallbacks
33 def get_credentials(self):
34@@ -578,9 +586,10 @@
35 folders = yield self.sd_client.get_folders()
36 shares = yield self.sd_client.get_shares()
37
38+ display_name = yield self._process_path(root_dir)
39 root_volume = {u'volume_id': u'', u'path': root_dir,
40 u'subscribed': True, u'type': self.ROOT_TYPE,
41- u'display_name': self._process_path(root_dir)}
42+ u'display_name': display_name}
43 self._volumes[u''] = root_volume
44
45 # group shares by the offering user
46@@ -618,7 +627,8 @@
47 logger.warning('volumes_info: udf %r already in the volumes '
48 'list (%r).', vid, self._volumes[vid])
49 folder[u'subscribed'] = bool(folder[u'subscribed'])
50- folder[u'display_name'] = self._process_path(folder[u'path'])
51+ display_name = yield self._process_path(folder[u'path'])
52+ folder[u'display_name'] = display_name
53 self._volumes[vid] = folder
54
55 folders.sort(key=operator.itemgetter('path'))
56@@ -678,7 +688,7 @@
57 @inlineCallbacks
58 def validate_path_for_folder(self, folder_path):
59 """Validate 'folder_path' for folder creation."""
60- user_home = os.path.expanduser('~')
61+ user_home = yield self.get_home_dir()
62 folder_path = append_path_sep(folder_path)
63
64 # handle folder_path not within '~' or links
65
66=== modified file 'ubuntuone/controlpanel/gui/qt/addfolder.py'
67--- ubuntuone/controlpanel/gui/qt/addfolder.py 2011-12-26 19:45:13 +0000
68+++ ubuntuone/controlpanel/gui/qt/addfolder.py 2012-01-26 12:48:23 +0000
69@@ -20,8 +20,6 @@
70
71 from __future__ import division
72
73-import os
74-
75 from PyQt4 import QtGui, QtCore
76 from twisted.internet import defer
77
78@@ -56,8 +54,9 @@
79 def on_clicked(self):
80 """The 'Sync another folder' button was clicked."""
81 # The options argument is because of LP: #835013
82+ home_dir = yield self.backend.get_home_dir()
83 folder = QtGui.QFileDialog.getExistingDirectory(
84- parent=self, directory=os.path.expanduser('~'),
85+ parent=self, directory=home_dir,
86 options=QtGui.QFileDialog.DontUseNativeDialog)
87 folder = unicode(QtCore.QDir.toNativeSeparators(folder))
88 logger.debug('on_add_folder_button_clicked: user requested folder '
89@@ -68,9 +67,8 @@
90
91 is_valid = yield self.backend.validate_path_for_folder(folder)
92 if not is_valid:
93- user_home = os.path.expanduser('~')
94 text = FOLDER_INVALID_PATH % {'folder_path': folder,
95- 'home_folder': user_home}
96+ 'home_folder': home_dir}
97 QtGui.QMessageBox.warning(self, '', text, CLOSE)
98 return
99
100
101=== modified file 'ubuntuone/controlpanel/gui/qt/tests/__init__.py'
102--- ubuntuone/controlpanel/gui/qt/tests/__init__.py 2011-10-24 21:48:27 +0000
103+++ ubuntuone/controlpanel/gui/qt/tests/__init__.py 2012-01-26 12:48:23 +0000
104@@ -127,6 +127,10 @@
105 self._called['get_credentials'] = ((), {})
106 return TOKEN
107
108+ def get_home_dir(self):
109+ """Fake home return."""
110+ return USER_HOME
111+
112
113 class CrashyBackendException(Exception):
114 """A faked backend crash."""
115
116=== modified file 'ubuntuone/controlpanel/gui/qt/tests/test_addfolder.py'
117--- ubuntuone/controlpanel/gui/qt/tests/test_addfolder.py 2011-12-26 19:45:13 +0000
118+++ ubuntuone/controlpanel/gui/qt/tests/test_addfolder.py 2012-01-26 12:48:23 +0000
119@@ -80,10 +80,11 @@
120 """When adding a new folder, the proper file chooser is raised."""
121 yield self.ui.click()
122
123+ home_dir = yield self.ui.backend.get_home_dir()
124 self.assertEqual(FakedFileDialog.args, ())
125 self.assertEqual(FakedFileDialog.kwargs, {
126 'options': gui.QtGui.QFileDialog.DontUseNativeDialog,
127- 'directory': os.path.expanduser('~'),
128+ 'directory': home_dir,
129 'parent': self.ui,
130 })
131
132
133=== modified file 'ubuntuone/controlpanel/sd_client/__init__.py'
134--- ubuntuone/controlpanel/sd_client/__init__.py 2011-08-24 19:56:19 +0000
135+++ ubuntuone/controlpanel/sd_client/__init__.py 2012-01-26 12:48:23 +0000
136@@ -108,6 +108,10 @@
137 """Disable udf_autosubscribe in the syncdaemon."""
138 return self.proxy.enable_udf_autosubscribe(False)
139
140+ def get_home_dir(self):
141+ """Retrieve the root information from syncdaemon."""
142+ return self.proxy.get_home_dir()
143+
144 def get_root_dir(self):
145 """Retrieve the root information from syncdaemon."""
146 return self.proxy.get_root_dir()
147
148=== modified file 'ubuntuone/controlpanel/tests/test_backend.py'
149--- ubuntuone/controlpanel/tests/test_backend.py 2011-10-24 21:48:27 +0000
150+++ ubuntuone/controlpanel/tests/test_backend.py 2012-01-26 12:48:23 +0000
151@@ -248,6 +248,10 @@
152 """Stop the file_sync service."""
153 self.actions.append('stop')
154
155+ def get_home_dir(self):
156+ """Grab the home dir."""
157+ return USER_HOME
158+
159 def get_root_dir(self):
160 """Grab the root dir."""
161 return ROOT_PATH
162@@ -784,10 +788,11 @@
163 self.be.wc.results[QUOTA_API] = SAMPLE_QUOTA_JSON
164
165 # root dir info
166+ display_name = yield self.be._process_path(ROOT_PATH)
167 self.root_volume = {
168 u'volume_id': u'', u'path': ROOT_PATH, u'subscribed': True,
169 u'type': self.be.ROOT_TYPE,
170- u'display_name': self.be._process_path(ROOT_PATH),
171+ u'display_name': display_name,
172 }
173
174 @inlineCallbacks
175@@ -831,7 +836,8 @@
176 folder = folder.copy()
177 folder[u'type'] = self.be.FOLDER_TYPE
178 folder[u'subscribed'] = bool(folder[u'subscribed'])
179- folder[u'display_name'] = self.be._process_path(folder[u'path'])
180+ display_name = yield self.be._process_path(folder[u'path'])
181+ folder[u'display_name'] = display_name
182 folders.append(folder)
183
184 # sort folders by path
185@@ -863,6 +869,26 @@
186 self.assertEqual(result, expected)
187
188 @inlineCallbacks
189+ def test_volumes_info_process_path(self):
190+ """The volumes_info method exercises its callback."""
191+ root_path = USER_HOME + os.path.sep + 'My Ubuntu' + USER_HOME
192+ self.patch(self.be.sd_client, 'get_root_dir', lambda: root_path)
193+ for item in SAMPLE_FOLDERS:
194+ path = item[u'path']
195+ path = path[len(USER_HOME) + 1:]
196+ item[u'path'] = os.path.join(root_path, path)
197+ self.patch(self.be.sd_client, 'shares', SAMPLE_SHARES)
198+ self.patch(self.be.sd_client, 'folders', SAMPLE_FOLDERS)
199+
200+ yield self.be.volumes_info()
201+ for item in SAMPLE_FOLDERS:
202+ key = item[u'volume_id']
203+ folder = self.be._volumes[key]
204+ display_name = folder['display_name']
205+ prefix = 'My Ubuntu' + USER_HOME
206+ self.assertTrue(display_name.startswith(prefix))
207+
208+ @inlineCallbacks
209 def test_volumes_info_without_storage_info(self):
210 """The volumes_info method exercises its callback."""
211 self.patch(self.be.sd_client, 'shares', SAMPLE_SHARES)
212
213=== modified file 'ubuntuone/controlpanel/tests/test_sd_client.py'
214--- ubuntuone/controlpanel/tests/test_sd_client.py 2012-01-23 20:15:09 +0000
215+++ ubuntuone/controlpanel/tests/test_sd_client.py 2012-01-26 12:48:23 +0000
216@@ -69,9 +69,10 @@
217 called = {}
218 shares = {}
219 folders = {}
220- root_dir = os.path.expanduser('~/Ubuntu One')
221- shares_dir = os.path.expanduser('~/.cache/ubuntuone/shares')
222- shares_dir_link = os.path.join(root_dir, 'Shared With Me')
223+ home_dir = u'/home/ñandu úser'
224+ root_dir = os.path.join(home_dir, u'Ubuntu One')
225+ shares_dir = os.path.join(home_dir, u'.cache/ubuntuone/shares')
226+ shares_dir_link = os.path.join(root_dir, u'Shared With Me')
227
228 @classmethod
229 def create_share(cls, name, accepted=False, subscribed=False):
230@@ -302,6 +303,10 @@
231 """Request a rescan from scratch for volume_id."""
232 self.called['rescan_from_scratch'] = volume_id
233
234+ def get_home_dir(self):
235+ """Return the root directory."""
236+ return self.home_dir
237+
238 def get_root_dir(self):
239 """Return the root directory."""
240 return self.root_dir

Subscribers

People subscribed via source and target branches