Merge lp:~nataliabidart/magicicada-gui/multiple-metadata-for-real into lp:magicicada-gui
- multiple-metadata-for-real
- Merge into trunk
Proposed by
Natalia Bidart
Status: | Merged |
---|---|
Approved by: | Natalia Bidart |
Approved revision: | 69 |
Merged at revision: | 66 |
Proposed branch: | lp:~nataliabidart/magicicada-gui/multiple-metadata-for-real |
Merge into: | lp:magicicada-gui |
Diff against target: |
588 lines (+183/-114) 4 files modified
data/ui/gui.glade (+3/-2) magicicada/__init__.py (+46/-37) magicicada/tests/test_magicicada.py (+132/-74) pylintrc (+2/-1) |
To merge this branch: | bzr merge lp:~nataliabidart/magicicada-gui/multiple-metadata-for-real |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Facundo Batista | Approve | ||
Review via email: mp+30853@code.launchpad.net |
Commit message
Description of the change
Multiple metadata windows are now supported. Yeyyyy!
To post a comment you must log in.
- 68. By Natalia Bidart
-
Fixing failing test.
Revision history for this message
Natalia Bidart (nataliabidart) wrote : | # |
> =======
> =
> [FAIL]: magicicada.
> adata_dialog_
Fixed!
- 69. By Natalia Bidart
-
Merged trunk in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'data/ui/gui.glade' |
2 | --- data/ui/gui.glade 2010-07-18 20:58:35 +0000 |
3 | +++ data/ui/gui.glade 2010-08-01 14:53:41 +0000 |
4 | @@ -256,13 +256,13 @@ |
5 | </packing> |
6 | </child> |
7 | <child> |
8 | - <object class="GtkToolButton" id="raw_metadata"> |
9 | + <object class="GtkToolButton" id="metadata"> |
10 | <property name="visible">True</property> |
11 | <property name="sensitive">False</property> |
12 | <property name="label" translatable="yes">Metadata</property> |
13 | <property name="use_underline">True</property> |
14 | <property name="stock_id">gtk-find</property> |
15 | - <signal name="clicked" handler="on_raw_metadata_clicked"/> |
16 | + <signal name="clicked" handler="on_metadata_clicked"/> |
17 | </object> |
18 | <packing> |
19 | <property name="expand">False</property> |
20 | @@ -980,6 +980,7 @@ |
21 | </object> |
22 | <object class="GtkFileChooserDialog" id="file_chooser"> |
23 | <property name="border_width">5</property> |
24 | + <property name="window_position">center</property> |
25 | <property name="type_hint">normal</property> |
26 | <property name="has_separator">False</property> |
27 | <property name="create_folders">False</property> |
28 | |
29 | === modified file 'magicicada/__init__.py' |
30 | --- magicicada/__init__.py 2010-07-18 20:58:35 +0000 |
31 | +++ magicicada/__init__.py 2010-08-01 14:53:41 +0000 |
32 | @@ -57,6 +57,13 @@ |
33 | logger.addHandler(console) |
34 | |
35 | |
36 | +# Instance of 'A' has no 'y' member |
37 | +# pylint: disable-msg=E1101 |
38 | + |
39 | +# Unused argument, we need them for GTK callbacks |
40 | +# pylint: disable-msg=W0613 |
41 | + |
42 | + |
43 | class MagicicadaUI(object): |
44 | """Magicicada GUI main class.""" |
45 | |
46 | @@ -97,8 +104,7 @@ |
47 | 'shares_to_me_view', 'shares_to_me_store', 'shares_to_me_close', |
48 | 'shares_to_others', 'shares_to_others_dialog', # shares_to_others |
49 | 'shares_to_others_view', 'shares_to_others_store', |
50 | - 'shares_to_others_close', |
51 | - 'raw_metadata', # raw metadata |
52 | + 'shares_to_others_close', 'metadata', # metadata |
53 | 'is_started', 'is_connected', 'is_online', # status bar images |
54 | 'status_label', 'status_icon', # status label and systray icon |
55 | 'metaq_view', 'contentq_view', # queues tree views |
56 | @@ -117,7 +123,7 @@ |
57 | self._make_view_sortable('shares_to_me') |
58 | self._make_view_sortable('shares_to_others') |
59 | |
60 | - self.raw_metadata_dialog = self._new_metadata_dialog() |
61 | + self.metadata_dialogs = {} |
62 | self.volumes = (self.folders, self.shares_to_me, self.shares_to_others) |
63 | self.windows = (self.main_window, self.about_dialog, |
64 | self.folders_dialog) |
65 | @@ -146,7 +152,6 @@ |
66 | self.widget_is_visible = lambda w: w.get_property('visible') |
67 | self.widget_enabled = lambda w: self.widget_is_visible(w) and \ |
68 | w.is_sensitive() |
69 | - self.last_metadata_path = None |
70 | self.update() |
71 | |
72 | def _make_view_sortable(self, view_name): |
73 | @@ -159,23 +164,24 @@ |
74 | col.connect('clicked', self.on_store_sort_column_changed, i, store) |
75 | self._sorting_order[store][i] = gtk.SORT_ASCENDING |
76 | |
77 | - def _new_metadata_dialog(self): |
78 | + def _new_metadata_dialog(self, path): |
79 | """Return a new metadata dialog.""" |
80 | - dialog = gtk.Dialog(title='Raw metadata', parent=self.main_window, |
81 | + dialog = gtk.Dialog(title='Metadata for %s' % path, |
82 | + parent=self.main_window, |
83 | flags=gtk.DIALOG_NO_SEPARATOR, |
84 | buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)) |
85 | dialog.set_size_request(600, 300) |
86 | - dialog.set_position(gtk.WIN_POS_CENTER) |
87 | - setattr(self, 'raw_metadata_dialog', dialog) |
88 | + # gtk.WIN_POS_CENTER makes dialog overlap |
89 | + dialog.set_position(gtk.WIN_POS_MOUSE) |
90 | |
91 | close_button = dialog.action_area.get_children()[-1] |
92 | - close_button.connect('clicked', self.on_raw_metadata_close_clicked) |
93 | - close_button.connect('activate', self.on_raw_metadata_close_clicked) |
94 | - setattr(self, 'raw_metadata_close', close_button) |
95 | + close_button.connect('clicked', self.on_metadata_close_clicked, path) |
96 | + close_button.connect('activate', self.on_metadata_close_clicked, path) |
97 | + dialog.close = close_button |
98 | |
99 | image = gtk.Image() |
100 | image.set_from_animation(self.loading_animation) |
101 | - setattr(self, 'raw_metadata_image', image) |
102 | + dialog.image = image |
103 | |
104 | dialog.get_child().add(image) |
105 | |
106 | @@ -183,9 +189,9 @@ |
107 | text_view.set_editable(False) |
108 | text_view.set_wrap_mode(gtk.WRAP_WORD) |
109 | dialog.get_child().add(text_view) |
110 | - setattr(self, 'raw_metadata_view', text_view) |
111 | + dialog.view = text_view |
112 | |
113 | - dialog.hide() # XXX to be fixed later |
114 | + self.metadata_dialogs[path] = dialog |
115 | return dialog |
116 | |
117 | # GTK callbacks |
118 | @@ -215,7 +221,7 @@ |
119 | """Stop syncdaemon.""" |
120 | for v in self.volumes: |
121 | v.set_sensitive(False) |
122 | - self.raw_metadata.set_sensitive(False) |
123 | + self.metadata.set_sensitive(False) |
124 | |
125 | if self.widget_enabled(self.disconnect): |
126 | self.on_disconnect_clicked(self.disconnect) |
127 | @@ -301,26 +307,28 @@ |
128 | |
129 | def on_file_chooser_show(self, widget, data=None): |
130 | """Close the file_chooser dialog.""" |
131 | - if self.last_metadata_path is None: |
132 | - self.file_chooser.set_current_folder(self._u1_root) |
133 | - |
134 | - def on_raw_metadata_close_clicked(self, widget, data=None): |
135 | - """Close the raw_metadata dialog.""" |
136 | - self.raw_metadata_dialog.hide() |
137 | - |
138 | - def on_raw_metadata_clicked(self, widget, data=None): |
139 | - """Show raw metadata for a path choosen by the user.""" |
140 | + #if self.last_metadata_path is None: |
141 | + self.file_chooser.set_current_folder(self._u1_root) |
142 | + |
143 | + def on_metadata_close_clicked(self, widget, path): |
144 | + """Close the metadata dialog.""" |
145 | + self.metadata_dialogs[path].destroy() |
146 | + |
147 | + def on_metadata_clicked(self, widget, data=None): |
148 | + """Show metadata for a path choosen by the user.""" |
149 | res = self.file_chooser.run() |
150 | self.file_chooser.hide() |
151 | if res != gtk.FILE_CHOOSER_ACTION_OPEN: |
152 | return |
153 | |
154 | - self.last_metadata_path = self.file_chooser.get_filename() |
155 | - self.sd.get_metadata(path=self.last_metadata_path) |
156 | - self.raw_metadata_view.hide() |
157 | - self.raw_metadata_image.show() |
158 | - self._start_loading(self.raw_metadata_image) |
159 | - self.raw_metadata_dialog.show() |
160 | + path = self.file_chooser.get_filename() |
161 | + assert path is not None |
162 | + dialog = self._new_metadata_dialog(path) |
163 | + self.sd.get_metadata(path) |
164 | + dialog.view.hide() |
165 | + dialog.image.show() |
166 | + self._start_loading(dialog.image) |
167 | + dialog.show() |
168 | |
169 | def on_status_icon_activate(self, widget, data=None): |
170 | """Systray icon was clicked.""" |
171 | @@ -362,7 +370,7 @@ |
172 | |
173 | for v in self.volumes: |
174 | v.set_sensitive(True) |
175 | - self.raw_metadata.set_sensitive(True) |
176 | + self.metadata.set_sensitive(True) |
177 | |
178 | self._update_queues_and_status(self.sd.current_state) |
179 | |
180 | @@ -457,14 +465,15 @@ |
181 | @log(logger) |
182 | def on_metadata_ready(self, path, metadata): |
183 | """Lower layer has the requested metadata for 'path'.""" |
184 | - logger.debug('on_metadata_ready: path: %r, last_metadata_path: %r', |
185 | - path, self.last_metadata_path) |
186 | - if path != self.last_metadata_path: |
187 | + logger.debug('on_metadata_ready: path: %r', path) |
188 | + if path not in self.metadata_dialogs: |
189 | return |
190 | - self.raw_metadata_image.hide() |
191 | - self.raw_metadata_view.show() |
192 | + |
193 | + dialog = self.metadata_dialogs[path] |
194 | + dialog.image.hide() |
195 | + dialog.view.show() |
196 | text = '\n'.join('%s: %s' % i for i in metadata.iteritems()) |
197 | - self.raw_metadata_view.get_buffer().set_text(text) |
198 | + dialog.view.get_buffer().set_text(text) |
199 | |
200 | # custom |
201 | |
202 | |
203 | === modified file 'magicicada/tests/test_magicicada.py' |
204 | --- magicicada/tests/test_magicicada.py 2010-07-28 21:48:34 +0000 |
205 | +++ magicicada/tests/test_magicicada.py 2010-08-01 14:53:41 +0000 |
206 | @@ -39,9 +39,16 @@ |
207 | |
208 | # It's ok to access private data in the test suite |
209 | # pylint: disable-msg=W0212 |
210 | + |
211 | # Arguments number differs from overridden method |
212 | # pylint: disable-msg=W0221 |
213 | |
214 | +# Instance of 'A' has no 'y' member |
215 | +# pylint: disable-msg=E1101 |
216 | + |
217 | +# Instance of 'A' has no 'y' member (but some types could not be inferred) |
218 | +# pylint: disable-msg=E1103 |
219 | + |
220 | |
221 | def process_gtk_pendings(): |
222 | """Process all gtk pending events.""" |
223 | @@ -74,7 +81,7 @@ |
224 | """A faked syncdaemon.""" |
225 | |
226 | def __init__(self): |
227 | - self._meta_path = None |
228 | + self._meta_paths = [] |
229 | |
230 | self.current_state = syncdaemon.State() |
231 | self.meta_queue = [] |
232 | @@ -100,7 +107,7 @@ |
233 | 'is_connected', True) |
234 | self.disconnect = lambda: \ |
235 | setattr(self.current_state, 'is_connected', False) |
236 | - self.get_metadata = lambda path: setattr(self, '_meta_path', path) |
237 | + self.get_metadata = lambda path: self._meta_paths.append(path) |
238 | |
239 | |
240 | class MagicicadaUITestCase(TestCase): |
241 | @@ -220,10 +227,12 @@ |
242 | self.assertTrue(sensitive if enabled else not sensitive, |
243 | msg % (widget_name, '' if enabled else 'not ')) |
244 | |
245 | - def assert_dialog_properties(self, dialog_name, title, size=(600, 300), |
246 | - modal=True): |
247 | + def assert_dialog_properties(self, dialog_name=None, title=None, |
248 | + size=(600, 300), modal=True, dialog=None): |
249 | """The dialog 'dialog_name' has correct properties.""" |
250 | - dialog = getattr(self.ui, dialog_name) |
251 | + assert (dialog_name is None) ^ (dialog is None) |
252 | + if dialog is None: |
253 | + dialog = getattr(self.ui, dialog_name) |
254 | actual = dialog.size_request() |
255 | msg = 'size must be %s (got %s instead).' |
256 | self.assertEquals(size, actual, msg % (size, actual)) |
257 | @@ -233,8 +242,10 @@ |
258 | msg % (dialog_name, '' if modal else 'not ')) |
259 | |
260 | position = dialog.get_property('window-position') |
261 | - self.assertEqual(gtk.WIN_POS_CENTER, position, |
262 | - '%s must be centered.' % dialog_name) |
263 | + expected = gtk.WIN_POS_CENTER if dialog_name is not None else \ |
264 | + gtk.WIN_POS_MOUSE |
265 | + msg = 'dialog must have %s position (got %s instead).' |
266 | + self.assertEqual(expected, position, msg % (expected, position)) |
267 | |
268 | actual = dialog.get_title() |
269 | msg = '%s title must be %s (got %s instead)' |
270 | @@ -1046,14 +1057,14 @@ |
271 | def test_volume_sorting(self): |
272 | """Test volume panel can be re-sorted.""" |
273 | for i, col in enumerate(self.volume_view.get_columns()): |
274 | - col.clicked() # click on the column |
275 | + col.clicked() # click on the column |
276 | self.assert_sort_order_correct(col, i, gtk.SORT_ASCENDING) |
277 | self.assert_sort_indicator_correct(col) |
278 | |
279 | - col.clicked() # click on the column, sort order must change |
280 | + col.clicked() # click on the column, sort order must change |
281 | self.assert_sort_order_correct(col, i, gtk.SORT_DESCENDING) |
282 | |
283 | - col.clicked() # click again, sort order must be the first one |
284 | + col.clicked() # click again, sort order must be the first one |
285 | self.assert_sort_order_correct(col, i, gtk.SORT_ASCENDING) |
286 | |
287 | |
288 | @@ -1125,7 +1136,7 @@ |
289 | class MagicicadaUIMetadataTestCase(MagicicadaUITestCase): |
290 | """UI test cases for metadata display.""" |
291 | |
292 | - name = 'raw_metadata' |
293 | + name = 'metadata' |
294 | |
295 | def setUp(self): |
296 | """Init.""" |
297 | @@ -1138,23 +1149,38 @@ |
298 | s = super(MagicicadaUIMetadataTestCase, self) |
299 | s.assert_widget_availability(self.name, enabled) |
300 | |
301 | - def assert_dialog_visibility(self, dialog, text_view, image): |
302 | + def assert_dialog_visibility(self, dialog, text_view, image, path=None): |
303 | """Check the visibility for dialog, text_view and image.""" |
304 | + if path is None: |
305 | + path = self.path |
306 | + |
307 | msg = '%s visibility should be %s (got %s instead).' |
308 | - visible = self.ui.widget_is_visible(self.ui.raw_metadata_dialog) |
309 | + metadata_dialog = self.ui.metadata_dialogs[path] |
310 | + visible = self.ui.widget_is_visible(metadata_dialog) |
311 | self.assertEqual(dialog, visible, |
312 | - msg % ('raw_metadata_dialog', dialog, visible)) |
313 | + msg % ('metadata_dialog', dialog, visible)) |
314 | |
315 | - visible = self.ui.widget_is_visible(self.ui.raw_metadata_view) |
316 | + visible = self.ui.widget_is_visible(metadata_dialog.view) |
317 | self.assertEqual(text_view, visible, |
318 | - msg % ('raw_metadata_view', text_view, visible)) |
319 | + msg % ('metadata_view', text_view, visible)) |
320 | |
321 | - visible = self.ui.widget_is_visible(self.ui.raw_metadata_image) |
322 | + visible = self.ui.widget_is_visible(metadata_dialog.image) |
323 | self.assertEqual(image, visible, |
324 | - msg % ('raw_metadata_image', image, visible)) |
325 | - |
326 | - def test_raw_metadata_are_disabled_until_started(self): |
327 | - """Raw metadata button is disabled until online.""" |
328 | + msg % ('metadata_image', image, visible)) |
329 | + |
330 | + def assert_buffer_content(self, path, expected): |
331 | + """Check that the buffer content is correct for 'path'.""" |
332 | + buff = self.ui.metadata_dialogs[path].view.get_buffer() |
333 | + self.assertTrue(buff is not None, |
334 | + 'buffer for metadata_view must not be None.') |
335 | + |
336 | + expected = '\n'.join('%s: %s' % i for i in expected.iteritems()) |
337 | + actual = buff.get_text(*buff.get_bounds()) |
338 | + msg = 'buffer content must be %s (got %s instead).' |
339 | + self.assertEqual(actual, expected, msg % (expected, actual)) |
340 | + |
341 | + def test_metadata_are_disabled_until_started(self): |
342 | + """Metadata button is disabled until online.""" |
343 | # disabled at startup |
344 | self.assert_widget_availability(enabled=False) |
345 | |
346 | @@ -1162,8 +1188,8 @@ |
347 | self.do_start() |
348 | self.assert_widget_availability(enabled=True) |
349 | |
350 | - def test_raw_metadata_are_enabled_until_stopped(self): |
351 | - """Raw metadata button is enabled until offline.""" |
352 | + def test_metadata_are_enabled_until_stopped(self): |
353 | + """Metadata button is enabled until offline.""" |
354 | self.do_connect() |
355 | self.assert_widget_availability(enabled=True) |
356 | |
357 | @@ -1183,12 +1209,12 @@ |
358 | self.ui.on_stopped() |
359 | self.assert_widget_availability(enabled=False) |
360 | |
361 | - def test_raw_metadata_close_hides_the_dialog(self): |
362 | - """Test raw_metadata close button emits RESPONSE_CLOSE when clicked.""" |
363 | - self.ui.raw_metadata_close.clicked() |
364 | - self.assertFalse(self.ui.widget_is_visible( |
365 | - self.ui.raw_metadata_dialog), |
366 | - 'raw_metadata_dialog should not be visible.') |
367 | + def test_metadata_close_hides_the_dialog(self): |
368 | + """Test metadata close button emits RESPONSE_CLOSE when clicked.""" |
369 | + dialog = self.ui._new_metadata_dialog(self.path) |
370 | + dialog.close.clicked() |
371 | + visible = self.ui.widget_is_visible(dialog) |
372 | + self.assertFalse(visible, 'metadata_dialog should not be visible.') |
373 | |
374 | def test_file_chooser_open_emits_response_ok(self): |
375 | """Test volume close button emits RESPONSE_CLOSE when clicked.""" |
376 | @@ -1203,14 +1229,10 @@ |
377 | self.assertEqual(gtk.FILE_CHOOSER_ACTION_OPEN, self.response, |
378 | 'open button should emit FILE_CHOOSER_ACTION_OPEN.') |
379 | |
380 | - def test_on_raw_metadata_clicked(self): |
381 | - """Test on_raw_metadata_clicked.""" |
382 | + def test_on_metadata_clicked(self): |
383 | + """Test on_metadata_clicked.""" |
384 | self.ui._u1_root = os.path.dirname(self.path) |
385 | |
386 | - self.assertFalse(self.ui.widget_is_visible( |
387 | - self.ui.raw_metadata_dialog), |
388 | - 'raw_metadata_dialog should not be visible.') |
389 | - |
390 | self.ui.file_chooser.set_filename(self.path) |
391 | |
392 | def test_file_chooser(): |
393 | @@ -1220,34 +1242,37 @@ |
394 | |
395 | gobject.timeout_add(100, test_and_click, |
396 | (self.ui.file_chooser_open, test_file_chooser)) |
397 | - self.ui.on_raw_metadata_clicked(self.ui.raw_metadata) |
398 | + self.ui.on_metadata_clicked(self.ui.metadata) |
399 | + |
400 | + # dialog must exist now |
401 | + dialog = self.ui.metadata_dialogs[self.path] |
402 | |
403 | self.assertFalse(self.ui.widget_is_visible(self.ui.file_chooser), |
404 | 'file_chooser must be visible after metadata clicked.') |
405 | self.assertEqual(self.path, self.ui.file_chooser.get_filename(), |
406 | 'filename returned by file chooser must be correct.') |
407 | |
408 | - # raw_metadata_dialog is enabled and shows the loading animation |
409 | + # metadata_dialog is enabled and shows the loading animation |
410 | self.assert_dialog_visibility(dialog=True, text_view=False, image=True) |
411 | - expected = self.ui.raw_metadata_image.get_animation() |
412 | + expected = dialog.image.get_animation() |
413 | self.assertEqual(self.ui.loading_animation, expected, |
414 | - 'raw_metadata_image must have the correct animation.') |
415 | + 'metadata_image must have the correct animation.') |
416 | |
417 | # Check that the metadata was asked to the SD |
418 | - self.assertEqual(self.ui.sd._meta_path, self.path) |
419 | + self.assertEqual(1, len(self.ui.sd._meta_paths)) |
420 | + self.assertEqual(self.ui.sd._meta_paths[0], self.path) |
421 | # SD will eventually callback us with the metadata |
422 | self.ui.on_metadata_ready(self.path, self.metadata) |
423 | |
424 | - # raw_metadata_dialog is enabled and shows the metadata |
425 | + # metadata_dialog is enabled and shows the metadata |
426 | self.assert_dialog_visibility(dialog=True, text_view=True, image=False) |
427 | |
428 | # user closes the dialog |
429 | - self.ui.raw_metadata_close.clicked() |
430 | + dialog.close.clicked() |
431 | |
432 | # dialog was closed already |
433 | - self.assertFalse(self.ui.widget_is_visible( |
434 | - self.ui.raw_metadata_dialog), |
435 | - 'raw_metadata_dialog should not be visible.') |
436 | + visible = self.ui.widget_is_visible(dialog) |
437 | + self.assertFalse(visible, 'metadata_dialog should not be visible.') |
438 | |
439 | def test_file_chooser_folder_is_u1root_when_visible(self): |
440 | """File chooser folder is ~/Ubuntu One only when visible.""" |
441 | @@ -1256,19 +1281,20 @@ |
442 | "shouldn't have U1 folder before becoming visible") |
443 | |
444 | gobject.timeout_add(100, self.ui.file_chooser_open.clicked) |
445 | - self.ui.on_raw_metadata_clicked(self.ui.raw_metadata) |
446 | + self.ui.file_chooser.run() |
447 | |
448 | self.assertEqual(self.ui.file_chooser.get_current_folder(), |
449 | UBUNTU_ONE_ROOT, |
450 | 'should have U1 folder after becoming visible') |
451 | |
452 | - def test_raw_metadata_dialog_properties(self): |
453 | - """The raw_metadata dialog has correct properties.""" |
454 | - title = self.name.replace('_', ' ').capitalize() |
455 | - self.assert_dialog_properties(dialog_name='raw_metadata_dialog', |
456 | - title=title, modal=False) |
457 | + def test_metadata_dialog_properties(self): |
458 | + """The metadata dialog has correct properties.""" |
459 | + title = '%s for %s' % (self.name.replace('_', ' ').capitalize(), |
460 | + self.path) |
461 | + dialog = self.ui._new_metadata_dialog(self.path) |
462 | + self.assert_dialog_properties(dialog=dialog, title=title, modal=False) |
463 | |
464 | - actual = self.ui.raw_metadata_view.get_wrap_mode() |
465 | + actual = dialog.view.get_wrap_mode() |
466 | msg = 'wrap mode for view must be gtk.WRAP_WORD (got %s instead).' |
467 | self.assertEqual(gtk.WRAP_WORD, actual, msg % actual) |
468 | |
469 | @@ -1288,51 +1314,83 @@ |
470 | self.patch(self.ui.sd, 'get_metadata', self.set_called) |
471 | gobject.timeout_add(100, test_and_click, |
472 | (self.ui.file_chooser_cancel, NO_OP)) |
473 | - self.ui.on_raw_metadata_clicked(self.ui.raw_metadata) |
474 | + self.ui.on_metadata_clicked(self.ui.metadata) |
475 | |
476 | self.assertFalse(self.called, |
477 | 'get_metadata should not be called if no file chosen.') |
478 | |
479 | def test_filename_is_stored_if_open_clicked(self): |
480 | - """Filename is stored as 'last_metadata_path' if user clicked open.""" |
481 | - self.assertTrue(self.ui.last_metadata_path is None, |
482 | - 'last_metadata_path must be None.') |
483 | + """Filename is stored in the metadata dicts if user clicked open.""" |
484 | + self.assertEqual(self.ui.metadata_dialogs, {}, |
485 | + 'dialogs must be empty.') |
486 | self.ui._u1_root = os.path.dirname(self.path) |
487 | self.ui.file_chooser.set_filename(self.path) |
488 | gobject.timeout_add(100, test_and_click, |
489 | (self.ui.file_chooser_open, NO_OP)) |
490 | - self.ui.on_raw_metadata_clicked(self.ui.raw_metadata) |
491 | + self.ui.on_metadata_clicked(self.ui.metadata) |
492 | |
493 | - self.assertEqual(self.path, self.ui.last_metadata_path, |
494 | - 'last_metadata_path should be what the user choose.') |
495 | + self.assertEqual([self.path], self.ui.metadata_dialogs.keys(), |
496 | + 'metadata dict keys should be what the user choose.') |
497 | |
498 | def test_on_metadata_ready(self): |
499 | - """Callback on_metadata_ready updates the raw_metadata_view.""" |
500 | + """Callback on_metadata_ready updates the metadata_view.""" |
501 | path = 'bla' |
502 | - self.ui.last_metadata_path = path |
503 | + self.ui.metadata_dialogs = {path: self.ui._new_metadata_dialog(path)} |
504 | self.ui.on_metadata_ready(path, self.metadata) |
505 | |
506 | - buff = self.ui.raw_metadata_view.get_buffer() |
507 | - self.assertTrue(buff is not None, |
508 | - 'buffer for raw_metadata_view must not be None.') |
509 | - |
510 | - expected = '\n'.join('%s: %s' % i for i in self.metadata.iteritems()) |
511 | - actual = buff.get_text(*buff.get_bounds()) |
512 | - msg = 'buffer content must be %s (got %s instead).' |
513 | - self.assertEqual(actual, expected, |
514 | - msg % (expected, actual)) |
515 | + self.assert_buffer_content(path, self.metadata) |
516 | |
517 | def test_on_metadata_ready_doesnt_update_if_last_path_doesnt_match(self): |
518 | - """Callback on_metadata_ready updates the raw_metadata_view.""" |
519 | - self.patch(self.ui.raw_metadata_view.get_buffer(), |
520 | - 'set_text', self.set_called) |
521 | + """Callback on_metadata_ready updates the metadata_view.""" |
522 | + self.patch(self.ui, '_new_metadata_dialog', self.set_called) |
523 | path = 'bla' |
524 | - self.ui.last_metadata_path = path + path |
525 | + assert path not in self.ui.metadata_dialogs |
526 | self.ui.on_metadata_ready(path, self.metadata) |
527 | |
528 | self.assertFalse(self.called, |
529 | 'view should not be updated if key is not last one.') |
530 | |
531 | + def test_two_metadata_windows(self): |
532 | + """More than one metadata window is allowed.""" |
533 | + self.patch(self.ui.file_chooser, 'run', |
534 | + lambda: gtk.FILE_CHOOSER_ACTION_OPEN) |
535 | + |
536 | + path1 = os.path.abspath(self.mktemp()) |
537 | + open(path1, 'w').close() |
538 | + assert os.path.exists(path1) |
539 | + meta1 = {'value': 'Lorem ipsum dolor sit amet.'} |
540 | + |
541 | + path2 = os.path.abspath(self.mktemp()) |
542 | + open(path2, 'w').close() |
543 | + assert os.path.exists(path2) |
544 | + meta2 = {'value': 'Etiam iaculis congue nisl.'} |
545 | + |
546 | + self.ui.file_chooser.get_filename = lambda: path1 |
547 | + self.ui.on_metadata_clicked(self.ui.metadata) |
548 | + |
549 | + self.ui.file_chooser.get_filename = lambda: path2 |
550 | + self.ui.on_metadata_clicked(self.ui.metadata) |
551 | + |
552 | + # Check that the UI has 2 metadata dialogs |
553 | + self.assertTrue(2, len(self.ui.metadata_dialogs)) |
554 | + |
555 | + # Check that the metadata was asked to the SD |
556 | + self.assertEqual(2, len(self.ui.sd._meta_paths)) |
557 | + self.assertEqual(self.ui.sd._meta_paths[0], path1) |
558 | + self.assertEqual(self.ui.sd._meta_paths[1], path2) |
559 | + |
560 | + # SD will eventually callback us with the metadata |
561 | + self.ui.on_metadata_ready(path1, meta1) |
562 | + # SD will eventually callback us with the metadata |
563 | + self.ui.on_metadata_ready(path2, meta2) |
564 | + |
565 | + self.assert_buffer_content(path1, meta1) |
566 | + self.assert_buffer_content(path2, meta2) |
567 | + |
568 | + # user closes the dialog |
569 | + self.ui.metadata_dialogs[path1].close.clicked() |
570 | + self.ui.metadata_dialogs[path2].close.clicked() |
571 | + |
572 | |
573 | def override_input_output(input_args, output_args): |
574 | """Call 'f' but receive fixed input and return fixed output.""" |
575 | |
576 | === modified file 'pylintrc' |
577 | --- pylintrc 2010-07-16 00:48:22 +0000 |
578 | +++ pylintrc 2010-08-01 14:53:41 +0000 |
579 | @@ -57,7 +57,8 @@ |
580 | |
581 | # Disable the message(s) with the given id(s). |
582 | W0108: Lambda may not be necessary |
583 | -disable-msg=W0142, W0613, W0108 |
584 | +R0923: Interface not implemented |
585 | +disable-msg=W0142, W0613, W0108, R0923 |
586 | |
587 | |
588 | [REPORTS] |
======= ======= ======= ======= ======= ======= ======= ======= ======= ======= ======= == tests.test_ magicicada. MagicicadaUIMet adataTestCase. test_metadata_ dialog_ properties
[FAIL]: magicicada.
Traceback (most recent call last): facundo/ devel/reps/ magicicada/ review_ multiple- metadata- for-real/ magicicada/ tests/test_ magicicada. py", line 1268, in test_metadata_ dialog_ properties assert_ dialog_ properties( dialog= dialog, title=title, modal=False) facundo/ devel/reps/ magicicada/ review_ multiple- metadata- for-real/ magicicada/ tests/test_ magicicada. py", line 221, in assert_ dialog_ properties trial.unittest. FailTest: None must be centered.
File "/home/
self.
File "/home/
'%s must be centered.' % dialog_name)
twisted.
not equal:
a = <enum GTK_WIN_POS_CENTER of type GtkWindowPosition>
b = <enum GTK_WIN_POS_MOUSE of type GtkWindowPosition>
------- ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- --
Ran 336 tests in 11.971s
FAILED (failures=1, successes=335)