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
=== modified file 'commit.py'
--- commit.py 2011-12-20 16:47:38 +0000
+++ commit.py 2012-01-22 14:44:24 +0000
@@ -114,6 +114,7 @@
114 self._enable_per_file_commits = True114 self._enable_per_file_commits = True
115 self._commit_all_changes = True115 self._commit_all_changes = True
116 self.committed_revision_id = None # Nothing has been committed yet116 self.committed_revision_id = None # Nothing has been committed yet
117 self._last_selected_file = None
117 self._saved_commit_messages_manager = SavedCommitMessagesManager(118 self._saved_commit_messages_manager = SavedCommitMessagesManager(
118 self._wt, self._wt.branch)119 self._wt, self._wt.branch)
119120
120121
=== modified file 'tests/test_commit.py'
--- tests/test_commit.py 2011-12-20 16:47:38 +0000
+++ tests/test_commit.py 2012-01-22 14:44:24 +0000
@@ -35,6 +35,7 @@
35 commit,35 commit,
36 commitmsgs,36 commitmsgs,
37 )37 )
38from bzrlib.plugins.gtk.commitmsgs import SavedCommitMessagesManager
3839
3940
40# TODO: All we need is basic ancestry code to test this, we shouldn't need a41# TODO: All we need is basic ancestry code to test this, we shouldn't need a
@@ -142,8 +143,47 @@
142 pass # With no widgets, there are no widgets to fill out143 pass # With no widgets, there are no widgets to fill out
143144
144145
146class MockMethod():
147
148 @classmethod
149 def bind(klass, test_instance, obj, method_name):
150 original_method = getattr(obj, method_name)
151 test_instance.addCleanup(setattr, obj, method_name, original_method)
152 setattr(obj, method_name, klass())
153
154 def __init__(self):
155 self.called = False
156 self.args = None
157 self.kwargs = None
158
159 def __call__(self, *args, **kwargs):
160 self.called = True
161 self.args = args
162 self.kwargs = kwargs
163
164
145class TestCommitDialogSimple(tests.TestCaseWithTransport):165class TestCommitDialogSimple(tests.TestCaseWithTransport):
146166
167 def test_init(self):
168 MockMethod.bind(self, CommitDialogNoWidgets, 'setup_params')
169 MockMethod.bind(self, CommitDialogNoWidgets, 'construct')
170 MockMethod.bind(self, CommitDialogNoWidgets, 'fill_in_data')
171
172 tree = self.make_branch_and_tree('tree')
173 rev_id = tree.commit('first')
174 dlg = CommitDialogNoWidgets(tree)
175 self.assertIs(tree, dlg._wt)
176 self.assertIs(None, dlg._selected)
177 self.assertTrue(dlg._enable_per_file_commits)
178 self.assertTrue(dlg._commit_all_changes)
179 self.assertIs(None, dlg.committed_revision_id)
180 self.assertIs(None, dlg._last_selected_file)
181 self.assertIsInstance(
182 dlg._saved_commit_messages_manager, SavedCommitMessagesManager)
183 self.assertTrue(CommitDialogNoWidgets.setup_params.called)
184 self.assertTrue(CommitDialogNoWidgets.construct.called)
185 self.assertTrue(CommitDialogNoWidgets.fill_in_data.called)
186
147 def test_setup_parameters_no_pending(self):187 def test_setup_parameters_no_pending(self):
148 tree = self.make_branch_and_tree('tree')188 tree = self.make_branch_and_tree('tree')
149 rev_id = tree.commit('first')189 rev_id = tree.commit('first')

Subscribers

People subscribed via source and target branches

to all changes: