Merge lp:~nataliabidart/ubuntuone-control-panel/default-folders into lp:ubuntuone-control-panel
- default-folders
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Natalia Bidart |
Approved revision: | 290 |
Merged at revision: | 287 |
Proposed branch: | lp:~nataliabidart/ubuntuone-control-panel/default-folders |
Merge into: | lp:ubuntuone-control-panel |
Diff against target: |
339 lines (+235/-8) 6 files modified
ubuntuone/controlpanel/logger.py (+2/-4) ubuntuone/controlpanel/utils/__init__.py (+5/-2) ubuntuone/controlpanel/utils/linux.py (+59/-0) ubuntuone/controlpanel/utils/tests/test_linux.py (+101/-1) ubuntuone/controlpanel/utils/tests/test_windows.py (+41/-0) ubuntuone/controlpanel/utils/windows.py (+27/-1) |
To merge this branch: | bzr merge lp:~nataliabidart/ubuntuone-control-panel/default-folders |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
dobey (community) | Approve | ||
Diego Sarmentero (community) | Approve | ||
Brian Curtin (community) | Approve | ||
Review via email: mp+97949@code.launchpad.net |
Commit message
- Implemented a method to list the user's default folders in every platform (part of LP: #933697).
Description of the change
Natalia Bidart (nataliabidart) wrote : | # |
> 94 + with open(dirs_path) as f:
> 95 + while True:
> 96 + line = f.readline()
>
> The file object you get back (f) is already iterable, so you could replace the
> "while True" with "for line in f"
>
> Other than this it looks alright.
Fixed and pushed, great catch! thanks
- 289. By Natalia Bidart
-
- Inprove default_folders file content iteration (thanks brian.curtin).
dobey (dobey) wrote : | # |
86 + if dirs_path is None:
87 + dirs_path = os.path.
We probably want to use xdg_config_home from dirspec.basedir here, instead of assuming ~/.config/.
With the suggestion from Brian, you can also drop the if line is None: break check.
Do we need to check that translated names for directories get handled correctly as well here, and ensure that unicode handling doesn't break again? I don't see a test for that case in your tests.
Also, on Windows, for the special folders you check for, which aren't supported on XP for example, how is that error handled? I suppose there should be a test which causes and checks for the error when that happens, to ensure we handle it properly? The linked MSDN page seems to suggest that _MYVIDEO doesn't exist on 5.0 (XP) for example. It might also be worth noting in the comment that if/when we drop XP support, we probably want to switch to _MYDOCUMENTS instead of _PERSONAL for that folder; as the documentation seems to suggest we should do.
Natalia Bidart (nataliabidart) wrote : | # |
> 86 + if dirs_path is None:
> 87 + dirs_path = os.path.
>
> We probably want to use xdg_config_home from dirspec.basedir here, instead of
> assuming ~/.config/.
Added.
> With the suggestion from Brian, you can also drop the if line is None: break
> check.
Done already.
> Do we need to check that translated names for directories get handled
> correctly as well here, and ensure that unicode handling doesn't break again?
> I don't see a test for that case in your tests.
Added tests for this.
> Also, on Windows, for the special folders you check for, which aren't
> supported on XP for example, how is that error handled? I suppose there should
> be a test which causes and checks for the error when that happens, to ensure
> we handle it properly? The linked MSDN page seems to suggest that _MYVIDEO
> doesn't exist on 5.0 (XP) for example. It might also be worth noting in the
> comment that if/when we drop XP support, we probably want to switch to
> _MYDOCUMENTS instead of _PERSONAL for that folder; as the documentation seems
> to suggest we should do.
Good catch, made the code more robust and added tests for it.
- 290. By Natalia Bidart
-
Better unicode management, and non existent folders.
dobey (dobey) : | # |
Preview Diff
1 | === modified file 'ubuntuone/controlpanel/logger.py' | |||
2 | --- ubuntuone/controlpanel/logger.py 2012-02-06 18:09:58 +0000 | |||
3 | +++ ubuntuone/controlpanel/logger.py 2012-03-16 20:00:25 +0000 | |||
4 | @@ -1,8 +1,6 @@ | |||
5 | 1 | # -*- coding: utf-8 -*- | 1 | # -*- coding: utf-8 -*- |
6 | 2 | |||
7 | 3 | # Authors: Natalia B Bidart <natalia.bidart@canonical.com> | ||
8 | 4 | # | 2 | # |
10 | 5 | # Copyright 2010 Canonical Ltd. | 3 | # Copyright 2010-2012 Canonical Ltd. |
11 | 6 | # | 4 | # |
12 | 7 | # This program is free software: you can redistribute it and/or modify it | 5 | # This program is free software: you can redistribute it and/or modify it |
13 | 8 | # under the terms of the GNU General Public License version 3, as published | 6 | # under the terms of the GNU General Public License version 3, as published |
14 | @@ -30,7 +28,7 @@ | |||
15 | 30 | from ubuntuone.platform.xdg_base_directory import ubuntuone_log_dir | 28 | from ubuntuone.platform.xdg_base_directory import ubuntuone_log_dir |
16 | 31 | 29 | ||
17 | 32 | 30 | ||
19 | 33 | if os.environ.get('DEBUG'): | 31 | if os.environ.get('U1_DEBUG'): |
20 | 34 | LOG_LEVEL = logging.DEBUG | 32 | LOG_LEVEL = logging.DEBUG |
21 | 35 | else: | 33 | else: |
22 | 36 | # Only log this level and above | 34 | # Only log this level and above |
23 | 37 | 35 | ||
24 | === modified file 'ubuntuone/controlpanel/utils/__init__.py' | |||
25 | --- ubuntuone/controlpanel/utils/__init__.py 2012-03-09 13:44:53 +0000 | |||
26 | +++ ubuntuone/controlpanel/utils/__init__.py 2012-03-16 20:00:25 +0000 | |||
27 | @@ -1,7 +1,6 @@ | |||
28 | 1 | # -*- coding: utf-8 -*- | 1 | # -*- coding: utf-8 -*- |
29 | 2 | |||
30 | 3 | # | 2 | # |
32 | 4 | # Copyright 2010 Canonical Ltd. | 3 | # Copyright 2010-2012 Canonical Ltd. |
33 | 5 | # | 4 | # |
34 | 6 | # This program is free software: you can redistribute it and/or modify it | 5 | # This program is free software: you can redistribute it and/or modify it |
35 | 7 | # under the terms of the GNU General Public License version 3, as published | 6 | # under the terms of the GNU General Public License version 3, as published |
36 | @@ -37,10 +36,14 @@ | |||
37 | 37 | if sys.platform == 'win32': | 36 | if sys.platform == 'win32': |
38 | 38 | from ubuntuone.controlpanel.utils import windows | 37 | from ubuntuone.controlpanel.utils import windows |
39 | 39 | are_updates_present = windows.are_updates_present | 38 | are_updates_present = windows.are_updates_present |
40 | 39 | default_folders = windows.default_folders | ||
41 | 40 | perform_update = windows.perform_update | 40 | perform_update = windows.perform_update |
42 | 41 | else: | 41 | else: |
43 | 42 | from ubuntuone.controlpanel.utils import linux | ||
44 | 42 | are_updates_present = lambda *args, **kwargs: False | 43 | are_updates_present = lambda *args, **kwargs: False |
45 | 44 | default_folders = linux.default_folders | ||
46 | 43 | perform_update = lambda *args, **kwargs: None | 45 | perform_update = lambda *args, **kwargs: None |
47 | 46 | |||
48 | 44 | # pylint: enable=C0103 | 47 | # pylint: enable=C0103 |
49 | 45 | 48 | ||
50 | 46 | 49 | ||
51 | 47 | 50 | ||
52 | === added file 'ubuntuone/controlpanel/utils/linux.py' | |||
53 | --- ubuntuone/controlpanel/utils/linux.py 1970-01-01 00:00:00 +0000 | |||
54 | +++ ubuntuone/controlpanel/utils/linux.py 2012-03-16 20:00:25 +0000 | |||
55 | @@ -0,0 +1,59 @@ | |||
56 | 1 | # -*- coding: utf-8 -*- | ||
57 | 2 | # | ||
58 | 3 | # Copyright 2012 Canonical Ltd. | ||
59 | 4 | # | ||
60 | 5 | # This program is free software: you can redistribute it and/or modify it | ||
61 | 6 | # under the terms of the GNU General Public License version 3, as published | ||
62 | 7 | # by the Free Software Foundation. | ||
63 | 8 | # | ||
64 | 9 | # This program is distributed in the hope that it will be useful, but | ||
65 | 10 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
66 | 11 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
67 | 12 | # PURPOSE. See the GNU General Public License for more details. | ||
68 | 13 | # | ||
69 | 14 | # You should have received a copy of the GNU General Public License along | ||
70 | 15 | # with this program. If not, see <http://www.gnu.org/licenses/>. | ||
71 | 16 | |||
72 | 17 | """Miscelaneous functions and constants for linux.""" | ||
73 | 18 | |||
74 | 19 | import codecs | ||
75 | 20 | import os | ||
76 | 21 | |||
77 | 22 | from dirspec.basedir import xdg_config_home | ||
78 | 23 | from ubuntuone.controlpanel.logger import setup_logging | ||
79 | 24 | |||
80 | 25 | |||
81 | 26 | logger = setup_logging('utils.linux') | ||
82 | 27 | |||
83 | 28 | |||
84 | 29 | def default_folders(user_home='', dirs_path=None): | ||
85 | 30 | """Return a list of the folders to add by default.""" | ||
86 | 31 | result = [] | ||
87 | 32 | |||
88 | 33 | if dirs_path is None: | ||
89 | 34 | dirs_path = os.path.join(xdg_config_home, u'user-dirs.dirs') | ||
90 | 35 | |||
91 | 36 | if not os.path.exists(dirs_path): | ||
92 | 37 | logger.warning('default_folders: dirs_path %r does not exist.', | ||
93 | 38 | dirs_path) | ||
94 | 39 | return result | ||
95 | 40 | |||
96 | 41 | # pylint: disable=W0702 | ||
97 | 42 | |||
98 | 43 | try: | ||
99 | 44 | with codecs.open(dirs_path, encoding='utf-8') as f: | ||
100 | 45 | for line in f: | ||
101 | 46 | if line.startswith(u'#'): | ||
102 | 47 | continue | ||
103 | 48 | |||
104 | 49 | try: | ||
105 | 50 | _, value = line.strip().split(u'=') | ||
106 | 51 | value = value.strip(u'"').replace(u'$HOME', user_home) | ||
107 | 52 | except: | ||
108 | 53 | logger.exception('default_folders: can not row %r:', line) | ||
109 | 54 | else: | ||
110 | 55 | result.append(value) | ||
111 | 56 | except: | ||
112 | 57 | logger.exception('default_folders: can not load file %r:', dirs_path) | ||
113 | 58 | |||
114 | 59 | return result | ||
115 | 0 | 60 | ||
116 | === modified file 'ubuntuone/controlpanel/utils/tests/test_linux.py' | |||
117 | --- ubuntuone/controlpanel/utils/tests/test_linux.py 2011-10-26 10:45:54 +0000 | |||
118 | +++ ubuntuone/controlpanel/utils/tests/test_linux.py 2012-03-16 20:00:25 +0000 | |||
119 | @@ -17,11 +17,35 @@ | |||
120 | 17 | 17 | ||
121 | 18 | """Test the linux utils functions.""" | 18 | """Test the linux utils functions.""" |
122 | 19 | 19 | ||
123 | 20 | import codecs | ||
124 | 21 | import os | ||
125 | 20 | 22 | ||
126 | 21 | from twisted.internet import defer | 23 | from twisted.internet import defer |
127 | 22 | 24 | ||
128 | 23 | from ubuntuone.controlpanel import utils | 25 | from ubuntuone.controlpanel import utils |
130 | 24 | from ubuntuone.controlpanel.tests import TestCase | 26 | from ubuntuone.controlpanel.tests import TestCase, USER_HOME |
131 | 27 | |||
132 | 28 | REAL_CONTENT = u""" | ||
133 | 29 | XDG_DESKTOP_DIR="$HOME/Desktop" | ||
134 | 30 | XDG_DOWNLOAD_DIR="$HOME/Downloads" | ||
135 | 31 | XDG_PUBLICSHARE_DIR="$HOME/Public" | ||
136 | 32 | XDG_DOCUMENTS_DIR="$HOME/Documents" | ||
137 | 33 | XDG_MUSIC_DIR="$HOME/Music" | ||
138 | 34 | XDG_PICTURES_DIR="$HOME/Pictures" | ||
139 | 35 | XDG_VIDEOS_DIR="$HOME/Videos" | ||
140 | 36 | """ | ||
141 | 37 | |||
142 | 38 | NON_ASCII = u""" | ||
143 | 39 | XDG_DESKTOP_DIR="$HOME/桌面" | ||
144 | 40 | XDG_DOWNLOAD_DIR="$HOME/下载" | ||
145 | 41 | XDG_DOCUMENTS_DIR="$HOME/文档" | ||
146 | 42 | """ | ||
147 | 43 | |||
148 | 44 | LATIN_1 = u""" | ||
149 | 45 | XDG_DESKTOP_DIR="$HOME/Súbeme" | ||
150 | 46 | XDG_DOWNLOAD_DIR="$HOME/Bájame" | ||
151 | 47 | XDG_DOCUMENTS_DIR="$HOME/Mis ñoños Documentos" | ||
152 | 48 | """ | ||
153 | 25 | 49 | ||
154 | 26 | 50 | ||
155 | 27 | class AutoupdaterTestCase(TestCase): | 51 | class AutoupdaterTestCase(TestCase): |
156 | @@ -36,3 +60,79 @@ | |||
157 | 36 | def test_perform_update(self): | 60 | def test_perform_update(self): |
158 | 37 | """Test the method that performs the update.""" | 61 | """Test the method that performs the update.""" |
159 | 38 | self.assertEqual(None, utils.perform_update()) | 62 | self.assertEqual(None, utils.perform_update()) |
160 | 63 | |||
161 | 64 | |||
162 | 65 | class DefaultFoldersTestCase(TestCase): | ||
163 | 66 | """Test suite for the default_folders retriever.""" | ||
164 | 67 | |||
165 | 68 | def _create_faked_file(self, content='', encoding=None): | ||
166 | 69 | """Create a faked file to be parsed and clean it up afterwards.""" | ||
167 | 70 | filename = './dirs-parser-test.dirs' | ||
168 | 71 | if os.path.exists(filename): | ||
169 | 72 | os.remove(filename) | ||
170 | 73 | |||
171 | 74 | if encoding is None: | ||
172 | 75 | encoding = 'utf-8' | ||
173 | 76 | |||
174 | 77 | with codecs.open(filename, 'w', encoding=encoding) as f: | ||
175 | 78 | f.write(content) | ||
176 | 79 | |||
177 | 80 | self.addCleanup(os.remove, filename) | ||
178 | 81 | |||
179 | 82 | return filename | ||
180 | 83 | |||
181 | 84 | def test_default_folders_not_file(self): | ||
182 | 85 | """Default folders are empty if the file does not exist.""" | ||
183 | 86 | path = 'foo/bar/baz/yadda/yo' | ||
184 | 87 | assert not os.path.exists(path) | ||
185 | 88 | actual = utils.default_folders(dirs_path=path) | ||
186 | 89 | |||
187 | 90 | self.assertEqual(actual, []) | ||
188 | 91 | |||
189 | 92 | def test_default_folders_empty_file(self): | ||
190 | 93 | """Default folders are empty if the file empty.""" | ||
191 | 94 | filename = self._create_faked_file(content='') | ||
192 | 95 | actual = utils.default_folders(dirs_path=filename) | ||
193 | 96 | |||
194 | 97 | self.assertEqual(actual, []) | ||
195 | 98 | |||
196 | 99 | def test_default_folders_only_comments(self): | ||
197 | 100 | """Default folders are empty if only comments in the file.""" | ||
198 | 101 | content = u"# yadda yadda\n# foo bar baz\n#puipuipui" | ||
199 | 102 | filename = self._create_faked_file(content=content) | ||
200 | 103 | actual = utils.default_folders(dirs_path=filename) | ||
201 | 104 | |||
202 | 105 | self.assertEqual(actual, []) | ||
203 | 106 | |||
204 | 107 | def test_default_folders_syntax_error(self): | ||
205 | 108 | """Default folders do not explode on syntax error.""" | ||
206 | 109 | content = u"foo ~ bar\nYADDA=DOO" | ||
207 | 110 | filename = self._create_faked_file(content=content) | ||
208 | 111 | actual = utils.default_folders(dirs_path=filename) | ||
209 | 112 | |||
210 | 113 | self.assertEqual(actual, [u'DOO']) | ||
211 | 114 | |||
212 | 115 | def test_default_folders_parsed(self): | ||
213 | 116 | """Default folders parses the content of the file.""" | ||
214 | 117 | filename = self._create_faked_file(content=REAL_CONTENT) | ||
215 | 118 | actual = utils.default_folders(user_home=USER_HOME, dirs_path=filename) | ||
216 | 119 | |||
217 | 120 | expected = (i.split(u'=')[1].strip(u'"') for i in REAL_CONTENT.split()) | ||
218 | 121 | expected = [i.replace(u'$HOME', USER_HOME) for i in expected] | ||
219 | 122 | self.assertEqual(actual, expected) | ||
220 | 123 | |||
221 | 124 | def test_default_folders_non_ascii(self): | ||
222 | 125 | """Default folders parses the content if it's non-ascii.""" | ||
223 | 126 | filename = self._create_faked_file(content=NON_ASCII) | ||
224 | 127 | actual = utils.default_folders(user_home=USER_HOME, dirs_path=filename) | ||
225 | 128 | |||
226 | 129 | expected = (i.split(u'=')[1].strip(u'"') for i in NON_ASCII.split()) | ||
227 | 130 | expected = [i.replace(u'$HOME', USER_HOME) for i in expected] | ||
228 | 131 | self.assertEqual(actual, expected) | ||
229 | 132 | |||
230 | 133 | def test_default_folders_bad_encoding(self): | ||
231 | 134 | """Default folders parses the content if it's non-ascii.""" | ||
232 | 135 | filename = self._create_faked_file(content=LATIN_1, encoding='latin-1') | ||
233 | 136 | actual = utils.default_folders(user_home=USER_HOME, dirs_path=filename) | ||
234 | 137 | |||
235 | 138 | self.assertEqual(actual, []) | ||
236 | 39 | 139 | ||
237 | === modified file 'ubuntuone/controlpanel/utils/tests/test_windows.py' | |||
238 | --- ubuntuone/controlpanel/utils/tests/test_windows.py 2011-11-15 12:36:15 +0000 | |||
239 | +++ ubuntuone/controlpanel/utils/tests/test_windows.py 2012-03-16 20:00:25 +0000 | |||
240 | @@ -87,6 +87,47 @@ | |||
241 | 87 | self.assertEqual(0, self._called[0][5]) | 87 | self.assertEqual(0, self._called[0][5]) |
242 | 88 | 88 | ||
243 | 89 | 89 | ||
244 | 90 | class DefaultFoldersTestCase(TestCase): | ||
245 | 91 | """Test the default_folders method.""" | ||
246 | 92 | |||
247 | 93 | def test_special_folders(self, names=None): | ||
248 | 94 | """Test that default_folders does the right thing.""" | ||
249 | 95 | folders = utils.default_folders() | ||
250 | 96 | |||
251 | 97 | if names is None: | ||
252 | 98 | names = ('PERSONAL', 'MYMUSIC', 'MYPICTURES', 'MYVIDEO') | ||
253 | 99 | |||
254 | 100 | self.assertEqual(len(folders), len(names)) | ||
255 | 101 | self.assertEqual(folders, [os.path.abspath(f) for f in folders]) | ||
256 | 102 | |||
257 | 103 | expected = [] | ||
258 | 104 | for name in names: | ||
259 | 105 | name = getattr(utils.windows.shellcon, 'CSIDL_%s' % name) | ||
260 | 106 | folder = utils.windows.shell.SHGetFolderPath(0, name, None, 0) | ||
261 | 107 | expected.append(folder.encode('utf8')) | ||
262 | 108 | |||
263 | 109 | self.assertEqual(sorted(folders), sorted(expected)) | ||
264 | 110 | |||
265 | 111 | def test_special_folders_with_error(self): | ||
266 | 112 | """Test that default_folders handles errors.""" | ||
267 | 113 | failing_name = 'MYVIDEO' | ||
268 | 114 | original_func = utils.windows.shell.SHGetFolderPath | ||
269 | 115 | |||
270 | 116 | class SomeError(Exception): | ||
271 | 117 | """For test only.""" | ||
272 | 118 | |||
273 | 119 | def fail_for_some(code, name, parent, flag): | ||
274 | 120 | """Custom failer.""" | ||
275 | 121 | fail = getattr(utils.windows.shellcon, 'CSIDL_%s' % failing_name) | ||
276 | 122 | if name == fail: | ||
277 | 123 | raise SomeError('The parameter is incorrect.') | ||
278 | 124 | else: | ||
279 | 125 | return original_func(code, name, parent, flag) | ||
280 | 126 | |||
281 | 127 | self.patch(utils.windows.shell, 'SHGetFolderPath', fail_for_some) | ||
282 | 128 | self.test_special_folders(names=('PERSONAL', 'MYMUSIC', 'MYPICTURES')) | ||
283 | 129 | |||
284 | 130 | |||
285 | 90 | class GetPathTestCase(TestCase): | 131 | class GetPathTestCase(TestCase): |
286 | 91 | """Test the code that is used for the auto update process.""" | 132 | """Test the code that is used for the auto update process.""" |
287 | 92 | 133 | ||
288 | 93 | 134 | ||
289 | === modified file 'ubuntuone/controlpanel/utils/windows.py' | |||
290 | --- ubuntuone/controlpanel/utils/windows.py 2012-03-09 00:47:47 +0000 | |||
291 | +++ ubuntuone/controlpanel/utils/windows.py 2012-03-16 20:00:25 +0000 | |||
292 | @@ -23,13 +23,15 @@ | |||
293 | 23 | # Avoid pylint error on Linux | 23 | # Avoid pylint error on Linux |
294 | 24 | # pylint: disable=F0401 | 24 | # pylint: disable=F0401 |
295 | 25 | import win32api | 25 | import win32api |
296 | 26 | |||
297 | 27 | from win32com.shell import shell, shellcon | ||
298 | 26 | # pylint: enable=F0401 | 28 | # pylint: enable=F0401 |
299 | 27 | from twisted.internet import defer | 29 | from twisted.internet import defer |
300 | 28 | from twisted.internet.utils import getProcessValue | 30 | from twisted.internet.utils import getProcessValue |
301 | 29 | 31 | ||
302 | 30 | from ubuntuone.controlpanel.logger import setup_logging | 32 | from ubuntuone.controlpanel.logger import setup_logging |
303 | 31 | 33 | ||
305 | 32 | logger = setup_logging('utils') | 34 | logger = setup_logging('utils.windows') |
306 | 33 | AUTOUPDATE_EXE_NAME = 'autoupdate-windows.exe' | 35 | AUTOUPDATE_EXE_NAME = 'autoupdate-windows.exe' |
307 | 34 | 36 | ||
308 | 35 | 37 | ||
309 | @@ -62,6 +64,30 @@ | |||
310 | 62 | defer.returnValue(result) | 64 | defer.returnValue(result) |
311 | 63 | 65 | ||
312 | 64 | 66 | ||
313 | 67 | def default_folders(user_home=None): | ||
314 | 68 | """Return a list of the folders to add by default.""" | ||
315 | 69 | # as per http://msdn.microsoft.com/en-us/library/windows/desktop/bb762181, | ||
316 | 70 | # SHGetFolderPath is deprecated, we should migrate to SHGetKnownFolderPath | ||
317 | 71 | # (http://msdn.microsoft.com/en-us/library/windows/desktop/bb762188) | ||
318 | 72 | # but the latter does not support XP | ||
319 | 73 | # (Minimum supported client: Windows Vista) | ||
320 | 74 | get_path = lambda name: shell.SHGetFolderPath( | ||
321 | 75 | 0, getattr(shellcon, name), None, 0).encode('utf8') | ||
322 | 76 | |||
323 | 77 | folders = [] | ||
324 | 78 | # More information on these constants at | ||
325 | 79 | # http://msdn.microsoft.com/en-us/library/bb762494 | ||
326 | 80 | for name in (u'PERSONAL', u'MYMUSIC', u'MYPICTURES', u'MYVIDEO'): | ||
327 | 81 | name = u'CSIDL_%s' % name | ||
328 | 82 | try: | ||
329 | 83 | folders.append(get_path(name)) | ||
330 | 84 | except: # pylint: disable=W0702 | ||
331 | 85 | logger.exception('default_folders: could not retrieve folder info ' | ||
332 | 86 | 'for name %r.', name) | ||
333 | 87 | |||
334 | 88 | return folders | ||
335 | 89 | |||
336 | 90 | |||
337 | 65 | def perform_update(): | 91 | def perform_update(): |
338 | 66 | """Spawn the autoupdate process and call the stop function.""" | 92 | """Spawn the autoupdate process and call the stop function.""" |
339 | 67 | update_path = _get_update_path() | 93 | update_path = _get_update_path() |
94 + with open(dirs_path) as f:
95 + while True:
96 + line = f.readline()
The file object you get back (f) is already iterable, so you could replace the "while True" with "for line in f"
Other than this it looks alright.