Merge lp:~gmb/launchpad/checkwatches-keyerror-oops-bug-496988 into lp:launchpad

Proposed by Graham Binns
Status: Merged
Approved by: Graham Binns
Approved revision: not available
Merged at revision: not available
Proposed branch: lp:~gmb/launchpad/checkwatches-keyerror-oops-bug-496988
Merge into: lp:launchpad
Diff against target: 116 lines (+100/-1)
2 files modified
lib/lp/bugs/scripts/checkwatches.py (+1/-1)
lib/lp/bugs/scripts/tests/test_checkwatches.py (+99/-0)
To merge this branch: bzr merge lp:~gmb/launchpad/checkwatches-keyerror-oops-bug-496988
Reviewer Review Type Date Requested Status
Данило Шеган (community) release-critical Approve
Brad Crittenden (community) code Approve
Review via email: mp+16204@code.launchpad.net

Commit message

KeyErrors in BugWatchUpdater._getExternalBugTrackersAndWatches() will no longer cause checkwatches to abort prematurely.

To post a comment you must log in.
Revision history for this message
Graham Binns (gmb) wrote :

This branch fixes bug 406988 by preventing KeyErrors from being raised with the BugWatchUpdater.

I've added a regression test for the bug and changed the offending line of code.

Revision history for this message
Brad Crittenden (bac) wrote :

Actually bug 496988, as shown below.

Revision history for this message
Brad Crittenden (bac) wrote :

With the addition of the comment to your final test, as discussed on IRC, this branch looks fine. Thanks for the fix.

review: Approve (code)
Revision history for this message
Данило Шеган (danilo) wrote :

Let's get those gnome bugwatches going again.

review: Approve (release-critical)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/bugs/scripts/checkwatches.py'
--- lib/lp/bugs/scripts/checkwatches.py 2009-11-28 08:31:15 +0000
+++ lib/lp/bugs/scripts/checkwatches.py 2009-12-15 16:31:16 +0000
@@ -462,7 +462,7 @@
462 remotesystem_for_others.sync_comments = False462 remotesystem_for_others.sync_comments = False
463463
464 for bug_watch in bug_watches:464 for bug_watch in bug_watches:
465 if (remote_products[bug_watch.remotebug] in465 if (remote_products.get(bug_watch.remotebug, None) in
466 self._syncable_gnome_products):466 self._syncable_gnome_products):
467 syncable_watches.append(bug_watch)467 syncable_watches.append(bug_watch)
468 else:468 else:
469469
=== added file 'lib/lp/bugs/scripts/tests/test_checkwatches.py'
--- lib/lp/bugs/scripts/tests/test_checkwatches.py 1970-01-01 00:00:00 +0000
+++ lib/lp/bugs/scripts/tests/test_checkwatches.py 2009-12-15 16:31:16 +0000
@@ -0,0 +1,99 @@
1# Copyright 2009 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3"""Checkwatches unit tests."""
4
5__metaclass__ = type
6
7import unittest
8import transaction
9
10from zope.component import getUtility
11
12from canonical.launchpad.scripts.logger import QuietFakeLogger
13from canonical.launchpad.interfaces import ILaunchpadCelebrities
14from canonical.testing import LaunchpadZopelessLayer
15
16from lp.bugs.externalbugtracker.bugzilla import BugzillaAPI
17from lp.bugs.scripts import checkwatches
18from lp.testing import TestCaseWithFactory
19
20
21def fudged_get_external_bugtracker(bugtracker):
22 """A version of get_external_bugtracker that returns BugzillaAPI."""
23 return BugzillaAPI(bugtracker.baseurl)
24
25
26class NonConnectingBugzillaAPI(BugzillaAPI):
27 """A non-connected version of the BugzillaAPI ExternalBugTracker."""
28
29 bugs = {
30 1: {'product': 'test-product'},
31 }
32
33 def getExternalBugTrackerToUse(self):
34 return self
35
36 def getProductsForRemoteBugs(self, remote_bugs):
37 """Return the products for some remote bugs.
38
39 This method is basically the same as that of the superclass but
40 without the call to initializeRemoteBugDB().
41 """
42 bug_products = {}
43 for bug_id in bug_ids:
44 # If one of the bugs we're trying to get the product for
45 # doesn't exist, just skip it.
46 try:
47 actual_bug_id = self._getActualBugId(bug_id)
48 except BugNotFound:
49 continue
50
51 bug_dict = self._bugs[actual_bug_id]
52 bug_products[bug_id] = bug_dict['product']
53
54 return bug_products
55
56
57class TestCheckwatchesWithSyncableGnomeProducts(TestCaseWithFactory):
58
59 layer = LaunchpadZopelessLayer
60
61 def setUp(self):
62 super(TestCheckwatchesWithSyncableGnomeProducts, self).setUp()
63
64 # We monkey-patch externalbugtracker.get_external_bugtracker()
65 # so that it always returns what we want.
66 self.original_get_external_bug_tracker = (
67 checkwatches.externalbugtracker.get_external_bugtracker)
68 checkwatches.externalbugtracker.get_external_bugtracker = (
69 fudged_get_external_bugtracker)
70
71 # Create an updater with a limited set of syncable gnome
72 # products.
73 self.updater = checkwatches.BugWatchUpdater(
74 transaction, QuietFakeLogger(), ['test-product'])
75
76 def tearDown(self):
77 checkwatches.externalbugtracker.get_external_bugtracker = (
78 self.original_get_external_bug_tracker)
79 super(TestCheckwatchesWithSyncableGnomeProducts, self).tearDown()
80
81 def test_bug_496988(self):
82 # Regression test for bug 496988. KeyErrors when looking for the
83 # remote product for a given bug shouldn't travel upwards and
84 # cause the script to abort.
85 gnome_bugzilla = getUtility(ILaunchpadCelebrities).gnome_bugzilla
86 bug_watch_1 = self.factory.makeBugWatch(
87 remote_bug=1, bugtracker=gnome_bugzilla)
88 bug_watch_2 = self.factory.makeBugWatch(
89 remote_bug=2, bugtracker=gnome_bugzilla)
90
91 # Calling this method shouldn't raise a KeyError, even though
92 # there's no bug 2 on the bug tracker that we pass to it.
93 self.updater._getExternalBugTrackersAndWatches(
94 gnome_bugzilla, [bug_watch_1, bug_watch_2])
95
96
97def test_suite():
98 return unittest.TestLoader().loadTestsFromName(__name__)
99