← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~cjwatson/launchpad/import-warnings into lp:launchpad

 

Colin Watson has proposed merging lp:~cjwatson/launchpad/import-warnings into lp:launchpad.

Commit message:
Fix several import policy violations.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/import-warnings/+merge/271790

Fix several import policy violations.

There are two remaining which I don't quite have the energy to fix now:

You should not import lp.bugs.model.bugtasksearch into:
    lp.bugs.browser.buglisting
You should not import lp.code.model.branch into:
    lp.code.feed.branch
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/import-warnings into lp:launchpad.
=== modified file 'lib/lp/code/browser/branch.py'
--- lib/lp/code/browser/branch.py	2015-09-18 10:38:27 +0000
+++ lib/lp/code/browser/branch.py	2015-09-21 10:22:52 +0000
@@ -119,14 +119,11 @@
 from lp.code.interfaces.branchmergeproposal import IBranchMergeProposal
 from lp.code.interfaces.branchtarget import IBranchTarget
 from lp.code.interfaces.codereviewvote import ICodeReviewVoteReference
-from lp.code.model.branch import Branch
-from lp.code.model.branchcollection import GenericBranchCollection
 from lp.registry.interfaces.person import IPersonSet
 from lp.registry.interfaces.productseries import IProductSeries
 from lp.registry.vocabularies import UserTeamsParticipationPlusSelfVocabulary
 from lp.services import searchbuilder
 from lp.services.config import config
-from lp.services.database.bulk import load_related
 from lp.services.database.constants import UTC_NOW
 from lp.services.feeds.browser import (
     BranchFeedLink,
@@ -516,12 +513,7 @@
     @cachedproperty
     def landing_candidates(self):
         """Return a decorated list of landing candidates."""
-        candidates = list(self.context.landing_candidates)
-        branches = load_related(
-            Branch, candidates, ['source_branchID', 'prerequisite_branchID'])
-        GenericBranchCollection.preloadVisibleStackedOnBranches(
-            branches, self.user)
-        return [proposal for proposal in candidates
+        return [proposal for proposal in self.context.landing_candidates
                 if check_permission('launchpad.View', proposal)]
 
     @property

=== modified file 'lib/lp/code/browser/gitlisting.py'
--- lib/lp/code/browser/gitlisting.py	2015-07-08 16:05:11 +0000
+++ lib/lp/code/browser/gitlisting.py	2015-09-21 10:22:52 +0000
@@ -10,7 +10,6 @@
     'TargetGitListingView',
     ]
 
-from storm.expr import Desc
 from zope.component import getUtility
 from zope.interface import (
     implementer,
@@ -26,7 +25,6 @@
     IGitNamespacePolicy,
     )
 from lp.code.interfaces.gitrepository import IGitRepositorySet
-from lp.code.model.gitrepository import GitRepository
 from lp.registry.interfaces.persondistributionsourcepackage import (
     IPersonDistributionSourcePackage,
     )
@@ -50,8 +48,8 @@
 
     def __init__(self, view, repo_collection):
         super(GitRepositoryBatchNavigator, self).__init__(
-            repo_collection.getRepositories(eager_load=True).order_by(
-                Desc(GitRepository.date_last_modified)),
+            repo_collection.getRepositories(
+                eager_load=True, order_by_date=True),
             view.request, size=config.launchpad.branchlisting_batch_size)
         self.view = view
         self.column_count = 2

=== modified file 'lib/lp/code/browser/gitref.py'
--- lib/lp/code/browser/gitref.py	2015-09-18 15:41:08 +0000
+++ lib/lp/code/browser/gitref.py	2015-09-21 10:22:52 +0000
@@ -41,8 +41,6 @@
 from lp.code.interfaces.codereviewvote import ICodeReviewVoteReference
 from lp.code.interfaces.gitref import IGitRef
 from lp.code.interfaces.gitrepository import IGitRepositorySet
-from lp.code.model.gitrepository import GitRepository
-from lp.services.database.bulk import load_related
 from lp.services.helpers import english_list
 from lp.services.propertycache import cachedproperty
 from lp.services.webapp import (
@@ -143,11 +141,7 @@
     @cachedproperty
     def landing_candidates(self):
         """Return a decorated list of landing candidates."""
-        candidates = list(self.context.landing_candidates)
-        load_related(
-            GitRepository, candidates,
-            ["source_git_repositoryID", "prerequisite_git_repositoryID"])
-        return [proposal for proposal in candidates
+        return [proposal for proposal in self.context.landing_candidates
                 if check_permission("launchpad.View", proposal)]
 
     def _getBranchCountText(self, count):

=== modified file 'lib/lp/code/browser/gitrepository.py'
--- lib/lp/code/browser/gitrepository.py	2015-09-18 15:41:08 +0000
+++ lib/lp/code/browser/gitrepository.py	2015-09-21 10:22:52 +0000
@@ -26,7 +26,6 @@
     copy_field,
     use_template,
     )
-from storm.expr import Desc
 from zope.event import notify
 from zope.formlib import form
 from zope.interface import (
@@ -236,17 +235,12 @@
     def __init__(self, view, context):
         self.context = context
         super(GitRefBatchNavigator, self).__init__(
-            self._branches, view.request,
+            self.context.branches_by_date, view.request,
             size=config.launchpad.branchlisting_batch_size)
         self.view = view
         self.column_count = 3
 
     @property
-    def _branches(self):
-        from lp.code.model.gitref import GitRef
-        return self.context.branches.order_by(Desc(GitRef.committer_date))
-
-    @property
     def table_class(self):
         # XXX: MichaelHudson 2007-10-18 bug=153894: This means there are two
         # ways of sorting a one-page branch listing, which is confusing and

=== modified file 'lib/lp/code/interfaces/gitcollection.py'
--- lib/lp/code/interfaces/gitcollection.py	2015-09-17 11:12:42 +0000
+++ lib/lp/code/interfaces/gitcollection.py	2015-09-21 10:22:52 +0000
@@ -54,7 +54,7 @@
             collection.
         """
 
-    def getRepositories(eager_load=False):
+    def getRepositories(eager_load=False, order_by_date=False):
         """Return a result set of all repositories in this collection.
 
         The returned result set will also join across the specified tables
@@ -64,6 +64,8 @@
 
         :param eager_load: If True trigger eager loading of all the related
             objects in the collection.
+        :param order_by_date: If True, order results by descending
+            modification date.
         """
 
     def getRepositoryIds():

=== modified file 'lib/lp/code/interfaces/gitrepository.py'
--- lib/lp/code/interfaces/gitrepository.py	2015-09-17 08:52:02 +0000
+++ lib/lp/code/interfaces/gitrepository.py	2015-09-21 10:22:52 +0000
@@ -236,6 +236,10 @@
         # Really IGitRef, patched in _schema_circular_imports.py.
         value_type=Reference(Interface)))
 
+    branches_by_date = Attribute(
+        "The branch references present in this repository, ordered by last "
+        "commit date.")
+
     subscriptions = exported(CollectionField(
         title=_("GitSubscriptions associated with this repository."),
         readonly=True,

=== modified file 'lib/lp/code/model/branch.py'
--- lib/lp/code/model/branch.py	2015-09-17 11:21:28 +0000
+++ lib/lp/code/model/branch.py	2015-09-21 10:22:52 +0000
@@ -179,6 +179,7 @@
 from lp.services.propertycache import cachedproperty
 from lp.services.webapp import urlappend
 from lp.services.webapp.authorization import check_permission
+from lp.services.webapp.interfaces import ILaunchBag
 
 
 @implementer(IBranch, IPrivacy, IInformationType)
@@ -474,10 +475,22 @@
     @property
     def landing_candidates(self):
         """See `IBranch`."""
-        return BranchMergeProposal.select("""
-            BranchMergeProposal.target_branch = %s AND
-            BranchMergeProposal.queue_status NOT IN %s
-            """ % sqlvalues(self, BRANCH_MERGE_PROPOSAL_FINAL_STATES))
+        # Circular import.
+        from lp.code.model.branchcollection import GenericBranchCollection
+
+        result = Store.of(self).find(
+            BranchMergeProposal, BranchMergeProposal.target_branch == self,
+            Not(BranchMergeProposal.queue_status.is_in(
+                BRANCH_MERGE_PROPOSAL_FINAL_STATES)))
+
+        def eager_load(rows):
+            user = getUtility(ILaunchBag).user
+            branches = load_related(
+                Branch, rows, ['source_branchID', 'prerequisite_branchID'])
+            GenericBranchCollection.preloadVisibleStackedOnBranches(
+                branches, user)
+
+        return DecoratedResultSet(result, pre_iter_hook=eager_load)
 
     @property
     def dependent_branches(self):

=== modified file 'lib/lp/code/model/gitcollection.py'
--- lib/lp/code/model/gitcollection.py	2015-09-17 11:12:42 +0000
+++ lib/lp/code/model/gitcollection.py	2015-09-21 10:22:52 +0000
@@ -198,13 +198,16 @@
         load_related(SourcePackageName, repositories, ['sourcepackagename_id'])
         load_related(Product, repositories, ['project_id'])
 
-    def getRepositories(self, find_expr=GitRepository, eager_load=False):
+    def getRepositories(self, find_expr=GitRepository, eager_load=False,
+                        order_by_date=False):
         """See `IGitCollection`."""
         all_tables = set(
             self._tables.values() + self._asymmetric_tables.values())
         tables = [GitRepository] + list(all_tables)
         expressions = self._getRepositoryExpressions()
         resultset = self.store.using(*tables).find(find_expr, *expressions)
+        if order_by_date:
+            resultset.order_by(Desc(GitRepository.date_last_modified))
 
         def do_eager_load(rows):
             repository_ids = set(repository.id for repository in rows)

=== modified file 'lib/lp/code/model/gitref.py'
--- lib/lp/code/model/gitref.py	2015-09-17 08:52:02 +0000
+++ lib/lp/code/model/gitref.py	2015-09-21 10:22:52 +0000
@@ -45,7 +45,9 @@
     BranchMergeProposal,
     BranchMergeProposalGetter,
     )
+from lp.services.database.bulk import load_related
 from lp.services.database.constants import UTC_NOW
+from lp.services.database.decoratedresultset import DecoratedResultSet
 from lp.services.database.enumcol import EnumCol
 from lp.services.database.interfaces import IStore
 from lp.services.database.stormbase import StormBase
@@ -175,13 +177,23 @@
     @property
     def landing_candidates(self):
         """See `IGitRef`."""
-        return Store.of(self).find(
+        # Circular import.
+        from lp.code.model.gitrepository import GitRepository
+
+        result = Store.of(self).find(
             BranchMergeProposal,
             BranchMergeProposal.target_git_repository == self.repository,
             BranchMergeProposal.target_git_path == self.path,
             Not(BranchMergeProposal.queue_status.is_in(
                 BRANCH_MERGE_PROPOSAL_FINAL_STATES)))
 
+        def eager_load(rows):
+            load_related(
+                GitRepository, rows,
+                ["source_git_repositoryID", "prerequisite_git_repositoryID"])
+
+        return DecoratedResultSet(result, pre_iter_hook=eager_load)
+
     @property
     def dependent_landings(self):
         """See `IGitRef`."""

=== modified file 'lib/lp/code/model/gitrepository.py'
--- lib/lp/code/model/gitrepository.py	2015-09-17 11:21:28 +0000
+++ lib/lp/code/model/gitrepository.py	2015-09-21 10:22:52 +0000
@@ -24,6 +24,7 @@
 from storm.expr import (
     And,
     Coalesce,
+    Desc,
     Insert,
     Join,
     Not,
@@ -417,6 +418,11 @@
             GitRef.path.startswith(u"refs/heads/")).order_by(GitRef.path)
 
     @property
+    def branches_by_date(self):
+        """See `IGitRepository`."""
+        return self.branches.order_by(Desc(GitRef.committer_date))
+
+    @property
     def default_branch(self):
         """See `IGitRepository`."""
         return self._default_branch

=== modified file 'lib/lp/soyuz/browser/archivesubscription.py'
--- lib/lp/soyuz/browser/archivesubscription.py	2015-07-08 16:05:11 +0000
+++ lib/lp/soyuz/browser/archivesubscription.py	2015-09-21 10:22:52 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2013 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2015 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Browser views related to archive subscriptions."""
@@ -14,10 +14,7 @@
     ]
 
 import datetime
-from operator import (
-    attrgetter,
-    itemgetter,
-    )
+from operator import attrgetter
 
 import pytz
 from zope.component import getUtility
@@ -43,13 +40,8 @@
 from lp.app.widgets.date import DateWidget
 from lp.app.widgets.popup import PersonPickerWidget
 from lp.registry.interfaces.person import IPersonSet
-from lp.services.database.bulk import load_related
 from lp.services.fields import PersonChoice
-from lp.services.propertycache import (
-    cachedproperty,
-    get_property_cache,
-    )
-from lp.services.webapp.authorization import precache_permission_for_objects
+from lp.services.propertycache import cachedproperty
 from lp.services.webapp.batching import (
     BatchNavigator,
     StormRangeFactory,
@@ -64,7 +56,6 @@
     IArchiveSubscriberSet,
     IPersonalArchiveSubscription,
     )
-from lp.soyuz.model.archive import Archive
 
 
 def archive_subscription_ui_adapter(archive_subscription):
@@ -329,14 +320,6 @@
         subs_with_tokens = subscriber_set.getBySubscriberWithActiveToken(
             self.context)
 
-        subscriptions = map(itemgetter(0), subs_with_tokens)
-        precache_permission_for_objects(None, 'launchpad.View', subscriptions)
-        archives = load_related(Archive, subscriptions, ['archive_id'])
-        list(getUtility(IPersonSet).getPrecachedPersonsFromIDs(
-            [archive.ownerID for archive in archives], need_validity=True))
-        for archive in archives:
-            get_property_cache(archive)._known_subscribers = [self.user]
-
         # Turn the result set into a list of dicts so it can be easily
         # accessed in TAL. Note that we need to ensure that only one
         # PersonalArchiveSubscription is included for each archive,

=== modified file 'lib/lp/soyuz/interfaces/archive.py'
--- lib/lp/soyuz/interfaces/archive.py	2015-09-16 06:53:39 +0000
+++ lib/lp/soyuz/interfaces/archive.py	2015-09-21 10:22:52 +0000
@@ -8,6 +8,7 @@
 __all__ = [
     'ALLOW_RELEASE_BUILDS',
     'AlreadySubscribed',
+    'ArchiveAlreadyDeleted',
     'ArchiveDependencyError',
     'ArchiveDisabled',
     'ArchiveNotPrivate',

=== modified file 'lib/lp/soyuz/model/archivesubscriber.py'
--- lib/lp/soyuz/model/archivesubscriber.py	2015-07-08 16:05:11 +0000
+++ lib/lp/soyuz/model/archivesubscriber.py	2015-09-21 10:22:52 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2011 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2015 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Database class for table ArchiveSubscriber."""
@@ -30,17 +30,25 @@
 from zope.component import getUtility
 from zope.interface import implementer
 
-from lp.registry.interfaces.person import validate_person
+from lp.registry.interfaces.person import (
+    IPersonSet,
+    validate_person,
+    )
 from lp.registry.model.person import Person
 from lp.registry.model.teammembership import TeamParticipation
+from lp.services.database.bulk import load_related
 from lp.services.database.constants import UTC_NOW
 from lp.services.database.decoratedresultset import DecoratedResultSet
 from lp.services.database.enumcol import DBEnum
 from lp.services.identity.interfaces.emailaddress import EmailAddressStatus
 from lp.services.identity.model.emailaddress import EmailAddress
+from lp.services.propertycache import get_property_cache
+from lp.services.webapp.authorization import precache_permission_for_objects
+from lp.services.webapp.interfaces import ILaunchBag
 from lp.soyuz.enums import ArchiveSubscriberStatus
 from lp.soyuz.interfaces.archiveauthtoken import IArchiveAuthTokenSet
 from lp.soyuz.interfaces.archivesubscriber import IArchiveSubscriber
+from lp.soyuz.model.archive import Archive
 from lp.soyuz.model.archiveauthtoken import ArchiveAuthToken
 
 
@@ -204,7 +212,20 @@
 
     def getBySubscriberWithActiveToken(self, subscriber, archive=None):
         """See `IArchiveSubscriberSet`."""
-        return self._getBySubscriber(subscriber, archive, True, True)
+        result = self._getBySubscriber(subscriber, archive, True, True)
+
+        def eager_load(rows):
+            user = getUtility(ILaunchBag).user
+            subscriptions = map(itemgetter(0), rows)
+            precache_permission_for_objects(
+                None, 'launchpad.View', subscriptions)
+            archives = load_related(Archive, subscriptions, ['archive_id'])
+            list(getUtility(IPersonSet).getPrecachedPersonsFromIDs(
+                [archive.ownerID for archive in archives], need_validity=True))
+            for archive in archives:
+                get_property_cache(archive)._known_subscribers = [user]
+
+        return DecoratedResultSet(result, pre_iter_hook=eager_load)
 
     def getByArchive(self, archive, current_only=True):
         """See `IArchiveSubscriberSet`."""


Follow ups