← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~stevenk/launchpad/destroy-getusedbugtags into lp:launchpad

 

Steve Kowalik has proposed merging lp:~stevenk/launchpad/destroy-getusedbugtags into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~stevenk/launchpad/destroy-getusedbugtags/+merge/118024

Destroy IBugTarget.getUsedBugTags(), get_bug_tags() -- they are only used in one place in BugEditView's validate method to make sure that new bug tags are explicitly created. Except the function is horrid and has at least XSS hole, perhaps more.

Due to the aforementioned death, BugEditView has been reduced to a shadow of its former self.
-- 
https://code.launchpad.net/~stevenk/launchpad/destroy-getusedbugtags/+merge/118024
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~stevenk/launchpad/destroy-getusedbugtags into lp:launchpad.
=== modified file 'lib/lp/bugs/browser/bug.py'
--- lib/lp/bugs/browser/bug.py	2012-07-31 09:41:51 +0000
+++ lib/lp/bugs/browser/bug.py	2012-08-03 02:04:21 +0000
@@ -701,6 +701,8 @@
         """Return the next URL to call when this call completes."""
         return canonical_url(self.context)
 
+    cancel_url = next_url
+
 
 class BugEditView(BugEditViewBase):
     """The view for the edit bug page."""
@@ -708,71 +710,18 @@
     field_names = ['title', 'description', 'tags']
     custom_widget('title', TextWidget, displayWidth=30)
     custom_widget('tags', BugTagsWidget)
-    next_url = None
-
-    _confirm_new_tags = False
-
-    def __init__(self, context, request):
-        """context is always an IBugTask."""
-        BugEditViewBase.__init__(self, context, request)
-        self.notifications = []
 
     @property
     def label(self):
         """The form label."""
         return 'Edit details for bug #%d' % self.context.bug.id
 
-    @property
-    def page_title(self):
-        """The page title."""
-        return self.label
-
-    @property
-    def cancel_url(self):
-        """See `LaunchpadFormView`."""
-        return canonical_url(self.context)
-
-    def validate(self, data):
-        """Make sure new tags are confirmed."""
-        if 'tags' not in data:
-            return
-        confirm_action = self.confirm_tag_action
-        if confirm_action.submitted():
-            # Validation is needed only for the change action.
-            return
-        bugtarget = self.context.target
-        newly_defined_tags = set(data['tags']).difference(
-            bugtarget.getUsedBugTags() + bugtarget.official_bug_tags)
-        # Display the confirm button in a notification message. We want
-        # it to be slightly smaller than usual, so we can't simply let
-        # it render itself.
-        confirm_button = (
-            '<input style="font-size: smaller" type="submit"'
-            ' value="%s" name="%s" />' % (
-                confirm_action.label, confirm_action.__name__))
-        for new_tag in newly_defined_tags:
-            self.notifications.append(
-                'The tag "%s" hasn\'t been used by %s before. %s' % (
-                    new_tag, bugtarget.bugtargetdisplayname, confirm_button))
-            self._confirm_new_tags = True
+    page_title = label
 
     @action('Change', name='change')
-    def edit_bug_action(self, action, data):
+    def change_action(self, action, data):
         """Update the bug with submitted changes."""
-        if not self._confirm_new_tags:
-            self.updateBugFromData(data)
-            self.next_url = canonical_url(self.context)
-
-    @action('Create the new tag', name='confirm_tag')
-    def confirm_tag_action(self, action, data):
-        """Define a new tag."""
-        self.actions['field.actions.change'].success(data)
-
-    def render(self):
-        """Render the page with only one submit button."""
-        # The confirmation button shouldn't be rendered automatically.
-        self.actions = [self.edit_bug_action]
-        return BugEditViewBase.render(self)
+        self.updateBugFromData(data)
 
 
 class BugMarkAsDuplicateView(BugEditViewBase):
@@ -782,11 +731,6 @@
     label = "Mark bug report as a duplicate"
     page_title = label
 
-    @property
-    def cancel_url(self):
-        """See `LaunchpadFormView`."""
-        return canonical_url(self.context)
-
     def setUpFields(self):
         """Make the readonly version of duplicateof available."""
         super(BugMarkAsDuplicateView, self).setUpFields()

=== modified file 'lib/lp/bugs/browser/configure.zcml'
--- lib/lp/bugs/browser/configure.zcml	2012-08-02 07:02:18 +0000
+++ lib/lp/bugs/browser/configure.zcml	2012-08-03 02:04:21 +0000
@@ -525,7 +525,7 @@
             name="+edit"
             for="lp.bugs.interfaces.bugtask.IBugTask"
             class="lp.bugs.browser.bug.BugEditView"
-            template="../templates/bug-edit.pt"
+            template="../../app/templates/generic-edit.pt"
             permission="launchpad.Edit"/>
         <browser:page
             name="+delete"

=== modified file 'lib/lp/bugs/browser/tests/bug-views.txt'
--- lib/lp/bugs/browser/tests/bug-views.txt	2012-04-12 22:50:15 +0000
+++ lib/lp/bugs/browser/tests/bug-views.txt	2012-08-03 02:04:21 +0000
@@ -649,21 +649,6 @@
     >>> bn_set = BugNotification.select(BugNotification.q.bugID == bug_one.id)
     >>> start_bugnotification_count = bn_set.count()
 
-Re-adding the same tag that already exists shouldn't notify anyone.
-
-    >>> edit_values['field.tags'] = u'doc doc'
-    >>> bug_edit.submit('change', edit_values)
-    >>> bug_edit.hasErrors()
-    False
-    >>> for message in bug_edit.view.notifications:
-    ...     print message
-
-    >>> bug_edit.wasRedirected()
-    True
-    >>> bn_set = BugNotification.select(BugNotification.q.bugID == bug_one.id)
-    >>> bn_set.count() == start_bugnotification_count
-    True
-
 The tag 'doc' has already been used for other Firefox bugs, let's try
 adding a tag that hasn't already been used. Add 'new-tag' multiple times
 so that we can verify that it will only be added once.
@@ -671,20 +656,6 @@
     >>> edit_values['field.tags'] = u'new-tag doc new-tag'
     >>> bug_edit.submit('change', edit_values)
 
-Now the form will have a notification, asking us to confirm that we indeed
-want to use a new tag. The notification includes a button, with which
-the user can confirm that he wants to add the tag.
-
-    >>> bug_edit.hasErrors()
-    False
-    >>> for message in bug_edit.view.notifications:
-    ...     print message
-    The tag "new-tag" hasn't been used by Mozilla Firefox before.
-    <input ...Create the new tag...>
-
-    >>> bug_edit.wasRedirected()
-    False
-
 The form still contains the 'Change' button, though, so that the user
 can edit the tag and submit the form again.
 
@@ -699,8 +670,6 @@
     >>> bug_edit.submit('confirm_tag', edit_values)
     >>> bug_edit.hasErrors()
     False
-    >>> bug_edit.wasRedirected()
-    True
 
     >>> bug_one.tags
     [u'doc', u'new-tag']

=== modified file 'lib/lp/bugs/doc/bug-tags.txt'
--- lib/lp/bugs/doc/bug-tags.txt	2012-04-04 05:46:26 +0000
+++ lib/lp/bugs/doc/bug-tags.txt	2012-08-03 02:04:21 +0000
@@ -286,57 +286,26 @@
 Tags for a context
 ------------------
 
-When viewing a bug listing for a context we want to display all the tags
-that are used in that context. For this we have a method on each bug
-target to return all the used tags. For source packages we return the
-tags used in its distribution/distroseries, since it's good to see
-which tags can be used. The tags are ordered alphabetically.  All tags
-are shown, no matter if they are used in open bugs or closed ones.
-
-    >>> from lp.bugs.interfaces.bugtask import BugTaskStatus
     >>> from lp.registry.interfaces.product import IProductSet
     >>> firefox = getUtility(IProductSet).getByName('firefox')
-    >>> login('test@xxxxxxxxxxxxx')
-    >>> for bugtask in firefox.searchTasks(BugTaskSearchParams(
-    ...     tag=all(u'layout-test'), user=None)):
-    ...     bugtask.transitionToStatus(
-    ...         BugTaskStatus.FIXRELEASED, getUtility(ILaunchBag).user)
-    >>> from lp.services.database.sqlbase import flush_database_updates
-    >>> flush_database_updates()
-
-    >>> firefox.getUsedBugTags()
-    [u'doc', u'layout-test', u'sco', u'svg']
-
     >>> from lp.registry.interfaces.projectgroup import IProjectGroupSet
     >>> mozilla = getUtility(IProjectGroupSet).getByName('mozilla')
-    >>> mozilla.getUsedBugTags()
-    [u'crash', u'doc', u'layout-test', u'sco', u'svg']
-
-    >>> ubuntu.getUsedBugTags()
-    [u'crash', u'dataloss', u'pebcak', u'sco', u'svg']
-
     >>> ubuntu_thunderbird = ubuntu.getSourcePackage('thunderbird')
-    >>> ubuntu_thunderbird.getUsedBugTags()
-    [u'crash', u'dataloss', u'pebcak', u'sco', u'svg']
-
     >>> debian = getUtility(IDistributionSet).getByName('debian')
     >>> debian_woody = debian.getSeries('woody')
-    >>> debian_woody.getUsedBugTags()
-    [u'dataloss', u'layout-test', u'pebcak']
-
     >>> debian_woody_firefox = (
     ...     debian_woody.getSourcePackage('mozilla-firefox'))
-    >>> debian_woody_firefox.getUsedBugTags()
-    [u'dataloss', u'layout-test', u'pebcak']
 
-We can also get all the used tags, together with the number of open
-bugs each tag has. Only tags having open bugs are returned.
+When viewing a bug listing for a context we want to display all the tags
+that are used in that context. We can also get all the used tags, together
+with the number of open bugs each tag has. Only tags having open bugs are
+returned.
 
     >>> sorted(firefox.getUsedBugTagsWithOpenCounts(None).items())
-    [(u'doc', 1L), (u'sco', 1L), (u'svg', 1L)]
+    [(u'doc', 1L), (u'layout-test', 1L), (u'sco', 1L), (u'svg', 1L)]
 
     >>> sorted(mozilla.getUsedBugTagsWithOpenCounts(None).items())
-    [(u'doc', 1L), (u'sco', 1L), (u'svg', 1L)]
+    [(u'doc', 1L), (u'layout-test', 1L), (u'sco', 1L), (u'svg', 1L)]
 
     >>> sorted(ubuntu.getUsedBugTagsWithOpenCounts(None).items())
     [(u'crash', 2L), (u'dataloss', 1L), (u'pebcak', 1L),
@@ -378,17 +347,3 @@
     True
     >>> ubuntu_thunderbird.getUsedBugTagsWithOpenCounts(sample_person)
     {u'crash': 1L}
-
-When context doesn't have any tags getUsedBugTags() returns a empty list.
-
-    >>> gimp = getUtility(IProjectGroupSet).getByName('gimp')
-    >>> gimp.getUsedBugTags()
-    []
-
-    >>> alsa = getUtility(IProductSet).getByName('alsa-utils')
-    >>> alsa.getUsedBugTags()
-    []
-
-    >>> gentoo = getUtility(IDistributionSet).getByName('gentoo')
-    >>> gentoo.getUsedBugTags()
-    []

=== modified file 'lib/lp/bugs/interfaces/bugtarget.py'
--- lib/lp/bugs/interfaces/bugtarget.py	2012-07-10 09:51:13 +0000
+++ lib/lp/bugs/interfaces/bugtarget.py	2012-08-03 02:04:21 +0000
@@ -381,9 +381,6 @@
         value_type=Tag(),
         readonly=True))
 
-    def getUsedBugTags():
-        """Return the tags used by the context as a sorted list of strings."""
-
     def getUsedBugTagsWithOpenCounts(user, tag_limit=0, include_tags=None):
         """Return name and bug count of tags having open bugs.
 

=== modified file 'lib/lp/bugs/model/bug.py'
--- lib/lp/bugs/model/bug.py	2012-08-03 00:30:51 +0000
+++ lib/lp/bugs/model/bug.py	2012-08-03 02:04:21 +0000
@@ -16,7 +16,6 @@
     'BugTag',
     'FileBugData',
     'get_also_notified_subscribers',
-    'get_bug_tags',
     'get_bug_tags_open_count',
     ]
 
@@ -245,21 +244,6 @@
     tag = StringCol(notNull=True)
 
 
-def get_bug_tags(context_clause):
-    """Return all the bug tags as a list of strings.
-
-    context_clause is a Storm clause, limiting the tags to a specific
-    context, which can only use the BugTask table to choose the context.
-    """
-    # Circular imports.
-    from lp.bugs.model.bugtask import BugTask
-
-    return list(IStore(BugTag).find(
-        BugTag.tag,
-        BugTag.bugID == BugTask.bugID, context_clause).group_by(
-            BugTag.tag).order_by(BugTag.tag))
-
-
 def get_bug_tags_open_count(context_condition, user, tag_limit=0,
     include_tags=None):
     """Worker for IBugTarget.getUsedBugTagsWithOpenCounts.

=== modified file 'lib/lp/bugs/stories/bug-tags/xx-tags-on-bug-page.txt'
--- lib/lp/bugs/stories/bug-tags/xx-tags-on-bug-page.txt	2012-06-22 17:02:50 +0000
+++ lib/lp/bugs/stories/bug-tags/xx-tags-on-bug-page.txt	2012-08-03 02:04:21 +0000
@@ -32,14 +32,6 @@
     >>> user_browser.getControl('Change').click()
 
 
-Since they are new tags, we have to confirm them.
-
-    >>> user_browser.url
-    'http://bugs.launchpad.dev/firefox/+bug/1/+edit'
-    >>> user_browser.getControl('Create the new tag', index=0).click()
-    >>> user_browser.url
-    'http://bugs.launchpad.dev/firefox/+bug/1'
-
 Now the tags will be displayed on the bug page:
 
     >>> 'Tags:' in user_browser.contents
@@ -87,27 +79,3 @@
     >>> print_bugtasks(anon_browser.contents)
     2 Blackhole Trash folder
       &mdash; Medium New
-
-Using official tags for the first time does not require confirmation.
-
-    >>> import transaction
-    >>> from zope.component import getUtility
-    >>> from lp.testing import login, logout
-    >>> from lp.registry.interfaces.product import IProductSet
-    >>> login('foo.bar@xxxxxxxxxxxxx')
-    >>> firefox = getUtility(IProductSet).getByName('firefox')
-    >>> u'an-official-tag' in firefox.getUsedBugTags()
-    False
-    >>> firefox.official_bug_tags = [u'an-official-tag']
-    >>> transaction.commit()
-    >>> logout()
-
-    >>> user_browser.open('http://bugs.launchpad.dev/firefox/+bug/1/+edit')
-    >>> user_browser.getControl('Tags').value = 'an-official-tag'
-    >>> user_browser.getControl('Change').click()
-    >>> user_browser.getControl('Create the new tag')
-    Traceback (most recent call last):
-    ...
-    LookupError: label 'Create the new tag'
-    >>> print user_browser.url
-    http://bugs.launchpad.dev/firefox/+bug/1

=== modified file 'lib/lp/bugs/stories/bugs/xx-bug-activity.txt'
--- lib/lp/bugs/stories/bugs/xx-bug-activity.txt	2012-07-17 21:41:42 +0000
+++ lib/lp/bugs/stories/bugs/xx-bug-activity.txt	2012-08-03 02:04:21 +0000
@@ -162,7 +162,6 @@
     ...     'http://bugs.launchpad.dev/redfish/+bug/15/+edit')
     >>> admin_browser.getControl("Tags").value = "tag1 tag2 tag3"
     >>> admin_browser.getControl("Change").click()
-    >>> admin_browser.getControl('Create the new tag', index=0).click()
 
     >>> admin_browser.open('http://launchpad.dev/bugs/15')
     >>> print_comments(admin_browser.contents)
@@ -182,7 +181,6 @@
     ...     'http://bugs.launchpad.dev/redfish/+bug/15/+edit')
     >>> admin_browser.getControl("Tags").value = "tag1 tag2 tag4"
     >>> admin_browser.getControl("Change").click()
-    >>> admin_browser.getControl('Create the new tag', index=0).click()
 
     >>> admin_browser.open('http://launchpad.dev/bugs/15')
     >>> print_comments(admin_browser.contents)

=== modified file 'lib/lp/bugs/stories/bugs/xx-bug-edit.txt'
--- lib/lp/bugs/stories/bugs/xx-bug-edit.txt	2012-06-16 13:21:23 +0000
+++ lib/lp/bugs/stories/bugs/xx-bug-edit.txt	2012-08-03 02:04:21 +0000
@@ -58,32 +58,13 @@
 ----------------
 
 When editing bug tags, we want to discourage people from adding new
-tags. Therefore, if you try to add a tag that hasn't been used in the
-current context before, you have to confirm that you indeed want to add
-the tag.
+tags.
 
     >>> user_browser.open('http://bugs.launchpad.dev/firefox/+bug/1')
     >>> user_browser.getLink(url="+edit").click()
     >>> user_browser.url
     'http://bugs.launchpad.dev/firefox/+bug/1/+edit'
 
-    >>> user_browser.getControl('Tags').value = 'new-tag'
-    >>> user_browser.getControl('Change').click()
-    >>> user_browser.url
-    'http://bugs.launchpad.dev/firefox/+bug/1/+edit'
-    >>> print user_browser.contents
-    <...The tag "new-tag" hasn't been used by Mozilla Firefox before...
-
-Here we can confirm that we want to add the tag, or change the tag name
-and submit the form again.
-
-    >>> user_browser.getControl('Create the new tag') is not None
-    True
-    >>> user_browser.getControl('Change') is not None
-    True
-
-Let's edit it, changing it to an existing tag.
-
     >>> user_browser.getControl('Tags').value = 'layout-test'
     >>> user_browser.getControl('Change').click()
 
@@ -102,7 +83,6 @@
     >>> user_browser.getControl('Tags').value = 'new-tag'
     >>> user_browser.getControl('Change').click()
 
-    >>> user_browser.getControl('Create the new tag').click()
     >>> user_browser.url
     'http://bugs.launchpad.dev/firefox/+bug/1'
 

=== removed file 'lib/lp/bugs/templates/bug-edit.pt'
--- lib/lp/bugs/templates/bug-edit.pt	2009-08-21 15:33:18 +0000
+++ lib/lp/bugs/templates/bug-edit.pt	1970-01-01 00:00:00 +0000
@@ -1,22 +0,0 @@
-<html
-  xmlns="http://www.w3.org/1999/xhtml";
-  xmlns:tal="http://xml.zope.org/namespaces/tal";
-  xmlns:metal="http://xml.zope.org/namespaces/metal";
-  xmlns:i18n="http://xml.zope.org/namespaces/i18n";
-  metal:use-macro="view/macro:page/main_only"
-  i18n:domain="malone"
->
-  <body>
-    <div metal:fill-slot="main">
-        <div metal:use-macro="context/@@launchpad_form/form">
-          <metal:extra_info metal:fill-slot="extra_info">
-            <p class="informational message"
-               tal:repeat="message view/notifications"
-               tal:content="structure message">
-              Confirmation message.
-            </p>
-          </metal:extra_info>
-        </div>
-    </div>
-  </body>
-</html>

=== modified file 'lib/lp/registry/configure.zcml'
--- lib/lp/registry/configure.zcml	2012-07-13 08:29:56 +0000
+++ lib/lp/registry/configure.zcml	2012-08-03 02:04:21 +0000
@@ -504,7 +504,6 @@
                 findRelatedArchives
                 getMergeProposals
                 getReleasesAndPublishingHistory
-                getUsedBugTags
                 getUsedBugTagsWithOpenCounts
                 getVersion
                 get_distroseries_packages

=== modified file 'lib/lp/registry/model/distribution.py'
--- lib/lp/registry/model/distribution.py	2012-08-03 00:30:51 +0000
+++ lib/lp/registry/model/distribution.py	2012-08-03 02:04:21 +0000
@@ -81,15 +81,11 @@
     DB_UNRESOLVED_BUGTASK_STATUSES,
     )
 from lp.bugs.interfaces.bugtaskfilter import OrderedBugTask
-from lp.bugs.model.bug import (
-    BugSet,
-    get_bug_tags,
-    )
+from lp.bugs.model.bug import BugSet
 from lp.bugs.model.bugtarget import (
     BugTargetBase,
     OfficialBugTagTargetMixin,
     )
-from lp.bugs.model.bugtask import BugTask
 from lp.bugs.model.structuralsubscription import (
     StructuralSubscriptionTargetMixin,
     )
@@ -627,10 +623,6 @@
         """Customize `search_params` for this distribution."""
         search_params.setDistribution(self)
 
-    def getUsedBugTags(self):
-        """See `IBugTarget`."""
-        return get_bug_tags(BugTask.distributionID == self.id)
-
     def getBranchTips(self, user=None, since=None):
         """See `IDistribution`."""
         # This, ignoring privacy issues, is what we want.

=== modified file 'lib/lp/registry/model/distributionsourcepackage.py'
--- lib/lp/registry/model/distributionsourcepackage.py	2012-05-15 03:16:08 +0000
+++ lib/lp/registry/model/distributionsourcepackage.py	2012-08-03 02:04:21 +0000
@@ -482,10 +482,6 @@
         """Customize `search_params` for this distribution source package."""
         search_params.setSourcePackage(self)
 
-    def getUsedBugTags(self):
-        """See `IBugTarget`."""
-        return self.distribution.getUsedBugTags()
-
     def _getOfficialTagClause(self):
         return self.distribution._getOfficialTagClause()
 

=== modified file 'lib/lp/registry/model/distroseries.py'
--- lib/lp/registry/model/distroseries.py	2012-08-01 07:10:54 +0000
+++ lib/lp/registry/model/distroseries.py	2012-08-03 02:04:21 +0000
@@ -55,9 +55,7 @@
 from lp.bugs.interfaces.bugsummary import IBugSummaryDimension
 from lp.bugs.interfaces.bugtarget import ISeriesBugTarget
 from lp.bugs.interfaces.bugtaskfilter import OrderedBugTask
-from lp.bugs.model.bug import get_bug_tags
 from lp.bugs.model.bugtarget import BugTargetBase
-from lp.bugs.model.bugtask import BugTask
 from lp.bugs.model.structuralsubscription import (
     StructuralSubscriptionTargetMixin,
     )
@@ -781,10 +779,6 @@
         """See `IHasBugs`."""
         return self.distribution.official_bug_tags
 
-    def getUsedBugTags(self):
-        """See `IHasBugs`."""
-        return get_bug_tags(BugTask.distroseriesID == self.id)
-
     @property
     def has_any_specifications(self):
         """See IHasSpecifications."""

=== modified file 'lib/lp/registry/model/product.py'
--- lib/lp/registry/model/product.py	2012-08-03 00:30:51 +0000
+++ lib/lp/registry/model/product.py	2012-08-03 02:04:21 +0000
@@ -92,10 +92,7 @@
 from lp.bugs.interfaces.bugsummary import IBugSummaryDimension
 from lp.bugs.interfaces.bugsupervisor import IHasBugSupervisor
 from lp.bugs.interfaces.bugtaskfilter import OrderedBugTask
-from lp.bugs.model.bug import (
-    BugSet,
-    get_bug_tags,
-    )
+from lp.bugs.model.bug import BugSet
 from lp.bugs.model.bugtarget import (
     BugTargetBase,
     OfficialBugTagTargetMixin,
@@ -889,10 +886,6 @@
         """Customize `search_params` for this product.."""
         search_params.setProduct(self)
 
-    def getUsedBugTags(self):
-        """See `IBugTarget`."""
-        return get_bug_tags(BugTask.productID == self.id)
-
     series = SQLMultipleJoin('ProductSeries', joinColumn='product',
         orderBy='name')
 

=== modified file 'lib/lp/registry/model/productseries.py'
--- lib/lp/registry/model/productseries.py	2012-08-01 07:10:54 +0000
+++ lib/lp/registry/model/productseries.py	2012-08-03 02:04:21 +0000
@@ -52,9 +52,7 @@
 from lp.bugs.interfaces.bugsummary import IBugSummaryDimension
 from lp.bugs.interfaces.bugtarget import ISeriesBugTarget
 from lp.bugs.interfaces.bugtaskfilter import OrderedBugTask
-from lp.bugs.model.bug import get_bug_tags
 from lp.bugs.model.bugtarget import BugTargetBase
-from lp.bugs.model.bugtask import BugTask
 from lp.bugs.model.structuralsubscription import (
     StructuralSubscriptionTargetMixin,
     )
@@ -442,10 +440,6 @@
         """See `IHasBugs`."""
         return self.product.official_bug_tags
 
-    def getUsedBugTags(self):
-        """See IBugTarget."""
-        return get_bug_tags(BugTask.productseriesID == self.id)
-
     def createBug(self, bug_params):
         """See IBugTarget."""
         raise NotImplementedError('Cannot file a bug against a productseries')

=== modified file 'lib/lp/registry/model/projectgroup.py'
--- lib/lp/registry/model/projectgroup.py	2012-08-01 07:10:54 +0000
+++ lib/lp/registry/model/projectgroup.py	2012-08-03 02:04:21 +0000
@@ -56,12 +56,10 @@
     )
 from lp.blueprints.model.sprint import HasSprintsMixin
 from lp.bugs.interfaces.bugsummary import IBugSummaryDimension
-from lp.bugs.model.bug import get_bug_tags
 from lp.bugs.model.bugtarget import (
     BugTargetBase,
     OfficialBugTag,
     )
-from lp.bugs.model.bugtask import BugTask
 from lp.bugs.model.structuralsubscription import (
     StructuralSubscriptionTargetMixin,
     )
@@ -334,13 +332,6 @@
         result.config(distinct=True)
         return result
 
-    def getUsedBugTags(self):
-        """See `IHasBugs`."""
-        if not self.products:
-            return []
-        return get_bug_tags(
-            BugTask.productID.is_in([p.id for p in self.products]))
-
     def getBugSummaryContextWhereClause(self):
         """See BugTargetBase."""
         # Circular fail.

=== modified file 'lib/lp/registry/model/sourcepackage.py'
--- lib/lp/registry/model/sourcepackage.py	2012-05-14 05:20:36 +0000
+++ lib/lp/registry/model/sourcepackage.py	2012-08-03 02:04:21 +0000
@@ -504,10 +504,6 @@
         """See `IHasBugs`."""
         return self.distroseries.official_bug_tags
 
-    def getUsedBugTags(self):
-        """See `IBugTarget`."""
-        return self.distroseries.getUsedBugTags()
-
     def getUsedBugTagsWithOpenCounts(self, user, tag_limit=0,
                                      include_tags=None):
         """See IBugTarget."""


Follow ups