← Back to team overview

launchpad-reviewers team mailing list archive

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

 

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

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #274735 in Launchpad itself: "Remove IHasBugs.*_bugtasks"
  https://bugs.launchpad.net/launchpad/+bug/274735

For more details, see:
https://code.launchpad.net/~stevenk/launchpad/destroy-ihasbugs-bugtasks/+merge/118439

Destroy IHasBugs.*_bugtasks and its callsites.
-- 
https://code.launchpad.net/~stevenk/launchpad/destroy-ihasbugs-bugtasks/+merge/118439
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~stevenk/launchpad/destroy-ihasbugs-bugtasks into lp:launchpad.
=== removed file 'lib/lp/bugs/doc/hasbugs.txt'
--- lib/lp/bugs/doc/hasbugs.txt	2011-12-30 06:14:56 +0000
+++ lib/lp/bugs/doc/hasbugs.txt	1970-01-01 00:00:00 +0000
@@ -1,95 +0,0 @@
-= IHasBugs =
-
-Objects that are linked to collections of bug tasks provide the IHasBugs
-interface. IHasBugs provides properties representing the relationship
-between the object and some of the bug tasks connected to it, and allows
-searching through the list of bugs.
-
-    >>> from zope.component import getUtility
-    >>> from lp.services.webapp.testing import verifyObject
-    >>> from lp.bugs.interfaces.bugtarget import IHasBugs
-    >>> from lp.registry.interfaces.distribution import IDistributionSet
-    >>> distroset = getUtility(IDistributionSet)
-    >>> debian = distroset.getByName("debian")
-    >>> debian_firefox = debian.getSourcePackage("mozilla-firefox")
-    >>> verifyObject(IHasBugs, debian_firefox)
-    True
-
-Open bugtasks:
-
-    >>> [bugtask.bug.id for bugtask in debian_firefox.open_bugtasks]
-    [1, 2, 3]
-
-Closed bugtasks:
-
-    >>> [bugtask.bug.id for bugtask in debian_firefox.closed_bugtasks]
-    [8]
-
-For the next couple of examples, we'll temporarily modify some bugtask
-values to have some sample data for the examples that follow.
-
-    >>> login("foo.bar@xxxxxxxxxxxxx")
-
-    >>> from lp.bugs.interfaces.bugtask import (
-    ...     BugTaskImportance,
-    ...     BugTaskStatus,
-    ...     IBugTaskSet,
-    ...     )
-
-    >>> bug_one_in_debian_firefox = getUtility(IBugTaskSet).get(4)
-    >>> bug_two_in_debian_firefox = getUtility(IBugTaskSet).get(5)
-    >>> bug_one_in_debian_firefox.transitionToImportance(
-    ...     BugTaskImportance.CRITICAL, getUtility(ILaunchBag).user)
-    >>> bug_one_in_debian_firefox.transitionToStatus(
-    ...     BugTaskStatus.INPROGRESS, getUtility(ILaunchBag).user)
-    >>> bug_two_in_debian_firefox.transitionToStatus(
-    ...     BugTaskStatus.INPROGRESS, getUtility(ILaunchBag).user)
-
-    >>> from lp.services.database.sqlbase import flush_database_updates
-    >>> flush_database_updates()
-
-Critical bugtasks:
-
-    >>> [bugtask.bug.id for bugtask in debian_firefox.critical_bugtasks]
-    [1]
-
-In progress bugtasks:
-
-    >>> [bugtask.bug.id for bugtask in debian_firefox.inprogress_bugtasks]
-    [1, 2]
-
-Unassigned bugtasks:
-
-    >>> [bugtask.bug.id for bugtask in debian_firefox.unassigned_bugtasks]
-    [1, 3]
-
-All bugtasks ever reported:
-
-    >>> [bugtask.bug.id for bugtask in debian_firefox.all_bugtasks]
-    [1, 2, 3, 8]
-
-IHasBugs.has_bugtasks is True if at least on bugtask exists.
-
-    >>> debian_firefox.has_bugtasks
-    True
-
-For a new product, has_bugtasks is False.
-
-    >>> product = factory.makeProduct()
-    >>> product.has_bugtasks
-    False
-
-When we add a bug, the property becomes True.
-
-    >>> bug = factory.makeBug(product=product)
-    >>> product.has_bugtasks
-    True
-
-Note that bugtasks having the status BugTaskStatus.UNKNOWN are not
-considered for has_bugtasks.
-
-    >>> from lp.bugs.interfaces.bugtask import BugTaskStatus
-    >>> bug.default_bugtask.transitionToStatus(
-    ...     BugTaskStatus.UNKNOWN, user=bug.owner)
-    >>> product.has_bugtasks
-    False

=== modified file 'lib/lp/bugs/interfaces/bugtarget.py'
--- lib/lp/bugs/interfaces/bugtarget.py	2012-08-03 01:42:13 +0000
+++ lib/lp/bugs/interfaces/bugtarget.py	2012-08-06 23:32:21 +0000
@@ -202,27 +202,6 @@
 
     export_as_webservice_entry()
 
-    # XXX Tom Berger 2008-09-26, Bug #274735
-    # The following are attributes, rather than fields, and must remain
-    # so, to make sure that they are not being copied into snapshots.
-    # Eventually, we'd like to remove these attributes from the content
-    # class altogether.
-    open_bugtasks = Attribute("A list of open bugTasks for this target.")
-    closed_bugtasks = Attribute("A list of closed bugTasks for this target.")
-    inprogress_bugtasks = Attribute(
-        "A list of in-progress bugTasks for this target.")
-    high_bugtasks = Attribute(
-        "A list of high importance BugTasks for this target.")
-    critical_bugtasks = Attribute(
-        "A list of critical BugTasks for this target.")
-    new_bugtasks = Attribute("A list of New BugTasks for this target.")
-    unassigned_bugtasks = Attribute(
-        "A list of unassigned BugTasks for this target.")
-    all_bugtasks = Attribute(
-        "A list of all BugTasks ever reported for this target.")
-    has_bugtasks = Attribute(
-        "True if a BugTask has ever been reported for this target.")
-
     # searchTasks devel API declaration.
     @call_with(search_params=None, user=REQUEST_USER)
     @operation_parameters(**search_tasks_params_for_api_devel)

=== modified file 'lib/lp/bugs/model/bugtarget.py'
--- lib/lp/bugs/model/bugtarget.py	2012-07-10 09:51:13 +0000
+++ lib/lp/bugs/model/bugtarget.py	2012-08-06 23:32:21 +0000
@@ -19,16 +19,12 @@
     Storm,
     Unicode,
     )
-from zope.component import getUtility
 from zope.interface import implements
 
 from lp.bugs.interfaces.bugtarget import IOfficialBugTag
 from lp.bugs.interfaces.bugtask import (
     BugTagsSearchCombinator,
-    BugTaskImportance,
     BugTaskSearchParams,
-    BugTaskStatus,
-    RESOLVED_BUGTASK_STATUSES,
     UNRESOLVED_BUGTASK_STATUSES,
     )
 from lp.bugs.interfaces.bugtaskfilter import simple_weight_calculator
@@ -39,17 +35,6 @@
     IMasterObject,
     IMasterStore,
     )
-from lp.services.searchbuilder import (
-    any,
-    not_equals,
-    NULL,
-    )
-from lp.services.webapp.interfaces import (
-    DEFAULT_FLAVOR,
-    ILaunchBag,
-    IStoreSelector,
-    MAIN_STORE,
-    )
 
 
 class HasBugsBase:
@@ -114,85 +99,6 @@
         """
         raise NotImplementedError(self.getBugSummaryContextWhereClause)
 
-    @property
-    def closed_bugtasks(self):
-        """See `IHasBugs`."""
-        closed_tasks_query = BugTaskSearchParams(
-            user=getUtility(ILaunchBag).user,
-            status=any(*RESOLVED_BUGTASK_STATUSES),
-            omit_dupes=True)
-
-        return self.searchTasks(closed_tasks_query)
-
-    @property
-    def open_bugtasks(self):
-        """See `IHasBugs`."""
-        return self.searchTasks(BugTaskSet().open_bugtask_search)
-
-    @property
-    def new_bugtasks(self):
-        """See `IHasBugs`."""
-        open_tasks_query = BugTaskSearchParams(
-            user=getUtility(ILaunchBag).user, status=BugTaskStatus.NEW,
-            omit_dupes=True)
-
-        return self.searchTasks(open_tasks_query)
-
-    @property
-    def high_bugtasks(self):
-        """See `IHasBugs`."""
-        high_tasks_query = BugTaskSearchParams(
-            user=getUtility(ILaunchBag).user,
-            importance=BugTaskImportance.HIGH,
-            status=any(*UNRESOLVED_BUGTASK_STATUSES),
-            omit_dupes=True)
-
-        return self.searchTasks(high_tasks_query)
-
-    @property
-    def critical_bugtasks(self):
-        """See `IHasBugs`."""
-        critical_tasks_query = BugTaskSearchParams(
-            user=getUtility(ILaunchBag).user,
-            importance=BugTaskImportance.CRITICAL,
-            status=any(*UNRESOLVED_BUGTASK_STATUSES),
-            omit_dupes=True)
-
-        return self.searchTasks(critical_tasks_query)
-
-    @property
-    def inprogress_bugtasks(self):
-        """See `IHasBugs`."""
-        inprogress_tasks_query = BugTaskSearchParams(
-            user=getUtility(ILaunchBag).user,
-            status=BugTaskStatus.INPROGRESS,
-            omit_dupes=True)
-
-        return self.searchTasks(inprogress_tasks_query)
-
-    @property
-    def unassigned_bugtasks(self):
-        """See `IHasBugs`."""
-        unassigned_tasks_query = BugTaskSearchParams(
-            user=getUtility(ILaunchBag).user, assignee=NULL,
-            status=any(*UNRESOLVED_BUGTASK_STATUSES), omit_dupes=True)
-
-        return self.searchTasks(unassigned_tasks_query)
-
-    @property
-    def all_bugtasks(self):
-        """See `IHasBugs`."""
-        all_tasks_query = BugTaskSearchParams(
-            user=getUtility(ILaunchBag).user,
-            status=not_equals(BugTaskStatus.UNKNOWN))
-
-        return self.searchTasks(all_tasks_query)
-
-    @property
-    def has_bugtasks(self):
-        """See `IHasBugs`."""
-        return not self.all_bugtasks.is_empty()
-
     def getBugTaskWeightFunction(self):
         """Default weight function is the simple one."""
         return simple_weight_calculator
@@ -242,9 +148,8 @@
 
     def _getOfficialTags(self):
         """Get the official bug tags as a sorted list of strings."""
-        store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR)
         target_clause = self._getOfficialTagClause()
-        return list(store.find(
+        return list(IMasterStore(OfficialBugTag).find(
             OfficialBugTag.tag, target_clause).order_by(OfficialBugTag.tag))
 
     def _setOfficialTags(self, tags):
@@ -265,9 +170,8 @@
 
         If the tag is not defined for this target, None is returned.
         """
-        store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR)
         target_clause = self._getOfficialTagClause()
-        return store.find(
+        return IMasterStore(OfficialBugTag).find(
             OfficialBugTag, OfficialBugTag.tag == tag, target_clause).one()
 
     def addOfficialBugTag(self, tag):
@@ -282,10 +186,9 @@
 
     def removeOfficialBugTag(self, tag):
         """See `IOfficialBugTagTarget`."""
-        store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR)
         tag = self._getTag(tag)
         if tag is not None:
-            store.remove(tag)
+            IMasterStore(OfficialBugTag).remove(tag)
 
 
 class OfficialBugTag(Storm):

=== modified file 'lib/lp/registry/browser/distributionsourcepackage.py'
--- lib/lp/registry/browser/distributionsourcepackage.py	2012-06-14 10:34:55 +0000
+++ lib/lp/registry/browser/distributionsourcepackage.py	2012-08-06 23:32:21 +0000
@@ -55,6 +55,10 @@
     StructuralSubscriptionTargetTraversalMixin,
     )
 from lp.bugs.interfaces.bug import IBugSet
+from lp.bugs.interfaces.bugtask import (
+    BugTaskSearchParams,
+    BugTaskStatus,
+    )
 from lp.registry.browser import add_subscribe_link
 from lp.registry.browser.pillar import PillarBugsMenu
 from lp.registry.interfaces.distributionsourcepackage import (
@@ -573,6 +577,13 @@
             uses_bugs=uses_bugs, uses_answers=uses_answers,
             uses_both=uses_both, uses_either=uses_either)
 
+    @cachedproperty
+    def new_bugtasks_count(self):
+        search_params = BugTaskSearchParams(
+            self.user, status=BugTaskStatus.NEW, omit_dupes=True)
+        search_params.setSourcePackage(self.context)
+        return self.context.searchTasks(search_params).count()
+
 
 class DistributionSourcePackageChangelogView(
     DistributionSourcePackageBaseView, LaunchpadView):

=== modified file 'lib/lp/registry/browser/person.py'
--- lib/lp/registry/browser/person.py	2012-07-08 17:34:32 +0000
+++ lib/lp/registry/browser/person.py	2012-08-06 23:32:21 +0000
@@ -147,6 +147,7 @@
     BugTaskStatus,
     IBugTaskSet,
     )
+from lp.bugs.model.bugtask import BugTaskSet
 from lp.buildmaster.enums import BuildStatus
 from lp.code.browser.sourcepackagerecipelisting import HasRecipesMenuMixin
 from lp.code.errors import InvalidNamespace
@@ -3592,10 +3593,11 @@
             project['title'] = pillar.title
             project['url'] = canonical_url(pillar)
             if IProduct.providedBy(pillar):
-                project['bug_count'] = product_bugtask_counts.get(pillar.id,
-                                                                  0)
+                project['bug_count'] = product_bugtask_counts.get(
+                    pillar.id, 0)
             else:
-                project['bug_count'] = pillar.open_bugtasks.count()
+                project['bug_count'] = pillar.searchTasks(
+                    BugTaskSet().open_bugtask_search).count()
             project['spec_count'] = pillar.specifications().count()
             project['question_count'] = pillar.searchQuestions().count()
             projects.append(project)

=== modified file 'lib/lp/registry/browser/tests/test_milestone.py'
--- lib/lp/registry/browser/tests/test_milestone.py	2012-07-10 10:40:13 +0000
+++ lib/lp/registry/browser/tests/test_milestone.py	2012-08-06 23:32:21 +0000
@@ -11,7 +11,10 @@
 from zope.component import getUtility
 
 from lp.app.interfaces.launchpad import ILaunchpadCelebrities
-from lp.bugs.interfaces.bugtask import IBugTaskSet
+from lp.bugs.interfaces.bugtask import (
+    BugTaskSearchParams,
+    IBugTaskSet,
+    )
 from lp.registry.enums import InformationType
 from lp.registry.interfaces.person import TeamSubscriptionPolicy
 from lp.registry.model.milestonetag import ProjectGroupMilestoneTag
@@ -179,7 +182,10 @@
         view = create_initialized_view(milestone, '+delete', form=form)
         self.assertEqual([], view.errors)
         self.assertEqual([], list(product.all_milestones))
-        self.assertEqual(0, product.development_focus.all_bugtasks.count())
+        search = BugTaskSearchParams(user=None, omit_dupes=True)
+        search.setTarget(product.development_focus)
+        tasks = product.development_focus.searchTasks(search)
+        self.assertEqual(0, tasks.count())
 
 
 class TestQueryCountBase(TestCaseWithFactory):

=== modified file 'lib/lp/registry/model/milestone.py'
--- lib/lp/registry/model/milestone.py	2012-07-24 06:39:54 +0000
+++ lib/lp/registry/model/milestone.py	2012-08-06 23:32:21 +0000
@@ -48,6 +48,7 @@
     IBugTaskSet,
     )
 from lp.bugs.model.bugtarget import HasBugsBase
+from lp.bugs.model.bugtask import BugTaskSet
 from lp.bugs.model.structuralsubscription import (
     StructuralSubscriptionTargetMixin,
     )
@@ -273,7 +274,8 @@
 
     def closeBugsAndBlueprints(self, user):
         """See `IMilestone`."""
-        for bugtask in self.open_bugtasks:
+        search = BugTaskSet().open_bugtask_search
+        for bugtask in self.searchTasks(search):
             if bugtask.status == BugTaskStatus.FIXCOMMITTED:
                 bugtask.bug.setStatus(
                     bugtask.target, BugTaskStatus.FIXRELEASED, user)

=== modified file 'lib/lp/registry/templates/distributionsourcepackage-index.pt'
--- lib/lp/registry/templates/distributionsourcepackage-index.pt	2012-06-20 03:10:55 +0000
+++ lib/lp/registry/templates/distributionsourcepackage-index.pt	2012-08-06 23:32:21 +0000
@@ -37,7 +37,7 @@
     <div id="structural-subscription-content-box"></div>
   </div>
   <div class="top-portlet" id="bugs-and-questions-summary"
-       tal:define="newbugs context/new_bugtasks/count;
+       tal:define="newbugs view/new_bugtasks_count;
                    open_questions view/open_questions/count">
     <div id="summary"
       tal:content="structure context/summary/fmt:text-to-html" />

=== modified file 'lib/lp/services/webapp/tests/test_batching.py'
--- lib/lp/services/webapp/tests/test_batching.py	2012-02-06 08:09:19 +0000
+++ lib/lp/services/webapp/tests/test_batching.py	2012-08-06 23:32:21 +0000
@@ -19,6 +19,7 @@
     )
 from zope.security.proxy import isinstance as zope_isinstance
 
+from lp.bugs.model.bugtask import BugTaskSet
 from lp.registry.model.person import Person
 from lp.services.database.decoratedresultset import DecoratedResultSet
 from lp.services.librarian.model import LibraryFileAlias
@@ -812,7 +813,9 @@
 
     def test_StormRangeFactory__empty_real_resultset(self):
         # StormRangeFactory works with empty regular result sets,
-        resultset = self.factory.makeProduct().open_bugtasks
+        product = self.factory.makeProduct()
+        resultset = product.development_focus.searchTasks(
+            BugTaskSet().open_bugtask_search)
         self.assertEqual(0, resultset.count())
         range_factory = StormRangeFactory(resultset)
         # rough_length is supposed to be zero, but the ANALYZE SELECT


Follow ups