Merge lp:~sinzui/bzr-gtk/precise-commit-0 into lp:bzr-gtk

Proposed by Curtis Hovey
Status: Merged
Merged at revision: 770
Proposed branch: lp:~sinzui/bzr-gtk/precise-commit-0
Merge into: lp:bzr-gtk
Diff against target: 71 lines (+41/-0)
2 files modified
commit.py (+1/-0)
tests/test_commit.py (+40/-0)
To merge this branch: bzr merge lp:~sinzui/bzr-gtk/precise-commit-0
Reviewer Review Type Date Requested Status
Jelmer Vernooij (community) Approve
Review via email: mp+89586@code.launchpad.net

Commit message

Define _last_selected_file in init so that async signal callbacks can use it.

Description of the change

I occasionally see the following traceback when committing use bzr-gtk
r769 on precise:

  File "/home/curtis/.bazaar/plugins/gtk/commit.py", line 579, in _on_treeview_files_cursor_changed
    self._update_per_file_info(selection)
  File "/home/curtis/.bazaar/plugins/gtk/commit.py", line 618, in _update_per_file_info
    self._save_current_file_message()
  File "/home/curtis/.bazaar/plugins/gtk/commit.py", line 605, in _save_current_file_message
    if self._last_selected_file is None:
AttributeError: 'CommitDialog' object has no attribute '_last_selected_file'

The commit is successful. Looking at the order of events,
_construct_file_list() connects _on_treeview_files_cursor_changed() to
the cursor-changed signal. _on_treeview_files_cursor_changed() presumes
_last_selected_file() was created, but it will not be created until
_fill_in_per_file_info() is called (which is two lines before
_construct_file_list())

The cursor-changed signal may have been called after _fill_in_per_file_info(),
but it is often called before with Gtk3.

--------------------------------------------------------------------

RULES

    * Ensure that CommitDialog._last_selected_file is defined before
      any signal callback is connected.

QA

While I do know the steps that I see the error, I do not always see it. Maybe
the issue only happens when there is a large tree of changes?
    * Run gcommit under precice
    * Type a few characters
    * Cancel the action
    * Save the message
    * Verify there is no AttributeError on strout

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

Thanks for adding tests, bzr-gtk has far too few. :-)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'commit.py'
2--- commit.py 2011-12-20 16:47:38 +0000
3+++ commit.py 2012-01-22 14:44:24 +0000
4@@ -114,6 +114,7 @@
5 self._enable_per_file_commits = True
6 self._commit_all_changes = True
7 self.committed_revision_id = None # Nothing has been committed yet
8+ self._last_selected_file = None
9 self._saved_commit_messages_manager = SavedCommitMessagesManager(
10 self._wt, self._wt.branch)
11
12
13=== modified file 'tests/test_commit.py'
14--- tests/test_commit.py 2011-12-20 16:47:38 +0000
15+++ tests/test_commit.py 2012-01-22 14:44:24 +0000
16@@ -35,6 +35,7 @@
17 commit,
18 commitmsgs,
19 )
20+from bzrlib.plugins.gtk.commitmsgs import SavedCommitMessagesManager
21
22
23 # TODO: All we need is basic ancestry code to test this, we shouldn't need a
24@@ -142,8 +143,47 @@
25 pass # With no widgets, there are no widgets to fill out
26
27
28+class MockMethod():
29+
30+ @classmethod
31+ def bind(klass, test_instance, obj, method_name):
32+ original_method = getattr(obj, method_name)
33+ test_instance.addCleanup(setattr, obj, method_name, original_method)
34+ setattr(obj, method_name, klass())
35+
36+ def __init__(self):
37+ self.called = False
38+ self.args = None
39+ self.kwargs = None
40+
41+ def __call__(self, *args, **kwargs):
42+ self.called = True
43+ self.args = args
44+ self.kwargs = kwargs
45+
46+
47 class TestCommitDialogSimple(tests.TestCaseWithTransport):
48
49+ def test_init(self):
50+ MockMethod.bind(self, CommitDialogNoWidgets, 'setup_params')
51+ MockMethod.bind(self, CommitDialogNoWidgets, 'construct')
52+ MockMethod.bind(self, CommitDialogNoWidgets, 'fill_in_data')
53+
54+ tree = self.make_branch_and_tree('tree')
55+ rev_id = tree.commit('first')
56+ dlg = CommitDialogNoWidgets(tree)
57+ self.assertIs(tree, dlg._wt)
58+ self.assertIs(None, dlg._selected)
59+ self.assertTrue(dlg._enable_per_file_commits)
60+ self.assertTrue(dlg._commit_all_changes)
61+ self.assertIs(None, dlg.committed_revision_id)
62+ self.assertIs(None, dlg._last_selected_file)
63+ self.assertIsInstance(
64+ dlg._saved_commit_messages_manager, SavedCommitMessagesManager)
65+ self.assertTrue(CommitDialogNoWidgets.setup_params.called)
66+ self.assertTrue(CommitDialogNoWidgets.construct.called)
67+ self.assertTrue(CommitDialogNoWidgets.fill_in_data.called)
68+
69 def test_setup_parameters_no_pending(self):
70 tree = self.make_branch_and_tree('tree')
71 rev_id = tree.commit('first')

Subscribers

People subscribed via source and target branches

to all changes: