launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #03543
[Merge] lp:~abentley/launchpad/person-product-merges into lp:launchpad
Aaron Bentley has proposed merging lp:~abentley/launchpad/person-product-merges into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #739921 in Launchpad itself: "The link "see all merge proposals" on person/product/+activereviews 404s"
https://bugs.launchpad.net/launchpad/+bug/739921
For more details, see:
https://code.launchpad.net/~abentley/launchpad/person-product-merges/+merge/60417
= Summary =
Fix bug #739921: The link "see all merge proposals" on person/product/+activereviews 404s Remove
== Proposed fix ==
Provide an adapter to convert PersonProduct into an IBranchCollection, and implement IHasMergeProposals on PersonProduct.
== Pre-implementation notes ==
None
== Implementation details ==
Implemented displayname on PersonProduct to support the view classes.
Various drive-by lint fixes.
== Tests ==
bin/test -t test_PersonProduct_implements_hasmergeproposals -t person_product
== Demo and Q/A ==
Create a merge proposal on a Product. Go to lpn/people/+me/PRODUCT/+merges. It should be displayed.
= Launchpad lint =
Checking for conflicts and issues in changed files.
Linting changed files:
lib/lp/code/model/tests/test_hasmergeproposals.py
lib/lp/code/configure.zcml
lib/lp/registry/interfaces/personproduct.py
lib/lp/code/adapters/branchcollection.py
lib/lp/code/browser/tests/test_branchmergeproposallisting.py
lib/lp/code/adapters/tests/test_branchcollection.py
lib/lp/registry/model/personproduct.py
--
https://code.launchpad.net/~abentley/launchpad/person-product-merges/+merge/60417
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~abentley/launchpad/person-product-merges into lp:launchpad.
=== modified file 'lib/lp/code/adapters/branchcollection.py'
--- lib/lp/code/adapters/branchcollection.py 2009-09-02 10:36:33 +0000
+++ lib/lp/code/adapters/branchcollection.py 2011-05-09 19:16:03 +0000
@@ -35,6 +35,13 @@
return getUtility(IAllBranches).ownedBy(person)
+def branch_collection_for_person_product(person_product):
+ """Adapt a PersonProduct to a branch collection."""
+ collection = getUtility(IAllBranches).ownedBy(person_product.person)
+ collection = collection.inProduct(person_product.product)
+ return collection
+
+
def branch_collection_for_distribution(distribution):
"""Adapt a distribution to a branch collection."""
return getUtility(IAllBranches).inDistribution(distribution)
=== added file 'lib/lp/code/adapters/tests/test_branchcollection.py'
--- lib/lp/code/adapters/tests/test_branchcollection.py 1970-01-01 00:00:00 +0000
+++ lib/lp/code/adapters/tests/test_branchcollection.py 2011-05-09 19:16:03 +0000
@@ -0,0 +1,32 @@
+# Copyright 2011 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Functional tests for BranchCollection adapters."""
+
+__metaclass__ = type
+
+
+from lp.code.interfaces.branchcollection import IBranchCollection
+from lp.testing import TestCaseWithFactory
+from lp.registry.model.personproduct import PersonProduct
+from canonical.testing.layers import DatabaseFunctionalLayer
+
+
+class TestPersonProduct(TestCaseWithFactory):
+
+ layer = DatabaseFunctionalLayer
+
+ def test_person_product(self):
+ product = self.factory.makeProduct()
+ person = self.factory.makePerson()
+ person_product = PersonProduct(person, product)
+ random_branch = self.factory.makeBranch()
+ product_branch = self.factory.makeProductBranch(product=product)
+ person_branch = self.factory.makeBranch(owner=person)
+ person_product_branch = self.factory.makeProductBranch(
+ owner=person, product=product)
+ branches = IBranchCollection(person_product).getBranches()
+ self.assertNotIn(random_branch, branches)
+ self.assertNotIn(product_branch, branches)
+ self.assertNotIn(person_branch, branches)
+ self.assertIn(person_product_branch, branches)
=== modified file 'lib/lp/code/browser/tests/test_branchmergeproposallisting.py'
--- lib/lp/code/browser/tests/test_branchmergeproposallisting.py 2010-12-02 16:13:51 +0000
+++ lib/lp/code/browser/tests/test_branchmergeproposallisting.py 2011-05-09 19:16:03 +0000
@@ -23,8 +23,10 @@
BranchMergeProposalStatus,
CodeReviewVote,
)
+from lp.registry.model.personproduct import PersonProduct
from lp.testing import (
ANONYMOUS,
+ BrowserTestCase,
login,
login_person,
TestCaseWithFactory,
@@ -179,6 +181,18 @@
self.assertEqual(4, comment_count)
+class TestMerges(BrowserTestCase):
+
+ layer = DatabaseFunctionalLayer
+
+ def test_person_product(self):
+ """The merges view should be enabled for PersonProduct."""
+ personproduct = PersonProduct(
+ self.factory.makePerson(), self.factory.makeProduct())
+ self.getViewBrowser(personproduct, '+merges',
+ rootsite='code')
+
+
class ActiveReviewGroupsTest(TestCaseWithFactory):
"""Tests for groupings used in for active reviews."""
@@ -276,9 +290,9 @@
# If the proposal is in needs review, the sort_key will be the
# date_review_requested.
bmp = self.factory.makeBranchMergeProposal(
- date_created=datetime(2009,6,1,tzinfo=pytz.UTC))
+ date_created=datetime(2009, 6, 1, tzinfo=pytz.UTC))
login_person(bmp.registrant)
- request_date = datetime(2009,7,1,tzinfo=pytz.UTC)
+ request_date = datetime(2009, 7, 1, tzinfo=pytz.UTC)
bmp.requestReview(request_date)
item = BranchMergeProposalListingItem(bmp, None, None)
self.assertEqual(request_date, item.sort_key)
@@ -287,13 +301,13 @@
# If the proposal is approved, the sort_key will default to the
# date_review_requested.
bmp = self.factory.makeBranchMergeProposal(
- date_created=datetime(2009,6,1,tzinfo=pytz.UTC))
+ date_created=datetime(2009, 6, 1, tzinfo=pytz.UTC))
login_person(bmp.target_branch.owner)
- request_date = datetime(2009,7,1,tzinfo=pytz.UTC)
+ request_date = datetime(2009, 7, 1, tzinfo=pytz.UTC)
bmp.requestReview(request_date)
bmp.approveBranch(
bmp.target_branch.owner, 'rev-id',
- datetime(2009,8,1,tzinfo=pytz.UTC))
+ datetime(2009, 8, 1, tzinfo=pytz.UTC))
item = BranchMergeProposalListingItem(bmp, None, None)
self.assertEqual(request_date, item.sort_key)
@@ -301,9 +315,9 @@
# If the proposal is approved and the review has been bypassed, the
# date_reviewed is used.
bmp = self.factory.makeBranchMergeProposal(
- date_created=datetime(2009,6,1,tzinfo=pytz.UTC))
+ date_created=datetime(2009, 6, 1, tzinfo=pytz.UTC))
login_person(bmp.target_branch.owner)
- review_date = datetime(2009,8,1,tzinfo=pytz.UTC)
+ review_date = datetime(2009, 8, 1, tzinfo=pytz.UTC)
bmp.approveBranch(
bmp.target_branch.owner, 'rev-id', review_date)
item = BranchMergeProposalListingItem(bmp, None, None)
@@ -312,7 +326,7 @@
def test_sort_key_wip(self):
# If the proposal is a work in progress, the date_created is used.
bmp = self.factory.makeBranchMergeProposal(
- date_created=datetime(2009,6,1,tzinfo=pytz.UTC))
+ date_created=datetime(2009, 6, 1, tzinfo=pytz.UTC))
login_person(bmp.target_branch.owner)
item = BranchMergeProposalListingItem(bmp, None, None)
self.assertEqual(bmp.date_created, item.sort_key)
@@ -328,13 +342,13 @@
product = self.factory.makeProduct()
bmp1 = self.factory.makeBranchMergeProposal(product=product)
login_person(bmp1.source_branch.owner)
- bmp1.requestReview(datetime(2009,6,1,tzinfo=pytz.UTC))
+ bmp1.requestReview(datetime(2009, 6, 1, tzinfo=pytz.UTC))
bmp2 = self.factory.makeBranchMergeProposal(product=product)
login_person(bmp2.source_branch.owner)
- bmp2.requestReview(datetime(2009,3,1,tzinfo=pytz.UTC))
+ bmp2.requestReview(datetime(2009, 3, 1, tzinfo=pytz.UTC))
bmp3 = self.factory.makeBranchMergeProposal(product=product)
login_person(bmp3.source_branch.owner)
- bmp3.requestReview(datetime(2009,1,1,tzinfo=pytz.UTC))
+ bmp3.requestReview(datetime(2009, 1, 1, tzinfo=pytz.UTC))
login(ANONYMOUS)
view = create_initialized_view(
product, name='+activereviews', rootsite='code')
=== modified file 'lib/lp/code/configure.zcml'
--- lib/lp/code/configure.zcml 2011-05-04 04:10:58 +0000
+++ lib/lp/code/configure.zcml 2011-05-09 19:16:03 +0000
@@ -122,6 +122,10 @@
provides="lp.code.interfaces.branchcollection.IBranchCollection"
factory="lp.code.adapters.branchcollection.branch_collection_for_product"/>
<adapter
+ for="lp.registry.interfaces.personproduct.IPersonProduct"
+ provides="lp.code.interfaces.branchcollection.IBranchCollection"
+ factory="lp.code.adapters.branchcollection.branch_collection_for_person_product"/>
+ <adapter
for="lp.registry.interfaces.projectgroup.IProjectGroup"
provides="lp.code.interfaces.branchcollection.IBranchCollection"
factory="lp.code.adapters.branchcollection.branch_collection_for_project"/>
=== modified file 'lib/lp/code/model/tests/test_hasmergeproposals.py'
--- lib/lp/code/model/tests/test_hasmergeproposals.py 2010-10-04 19:50:45 +0000
+++ lib/lp/code/model/tests/test_hasmergeproposals.py 2011-05-09 19:16:03 +0000
@@ -7,8 +7,10 @@
import unittest
+from canonical.launchpad.webapp.testing import verifyObject
from canonical.testing.layers import DatabaseFunctionalLayer
from lp.code.interfaces.hasbranches import IHasMergeProposals
+from lp.registry.model.personproduct import PersonProduct
from lp.testing import TestCaseWithFactory
@@ -32,7 +34,12 @@
project = self.factory.makeProject()
self.assertProvides(project, IHasMergeProposals)
+ def test_PersonProduct_implements_hasmergeproposals(self):
+ # PersonProducts should implement IHasMergeProposals.
+ product = self.factory.makeProduct()
+ person_product = PersonProduct(product.owner, product)
+ verifyObject(IHasMergeProposals, person_product)
+
def test_suite():
return unittest.TestLoader().loadTestsFromName(__name__)
-
=== modified file 'lib/lp/registry/interfaces/personproduct.py'
--- lib/lp/registry/interfaces/personproduct.py 2010-08-20 20:31:18 +0000
+++ lib/lp/registry/interfaces/personproduct.py 2011-05-09 19:16:03 +0000
@@ -13,22 +13,27 @@
from lazr.restful.fields import Reference
from zope.interface import Interface
+from zope.schema import (
+ TextLine,
+)
+from lp.code.interfaces.hasbranches import IHasMergeProposals
from lp.registry.interfaces.person import IPerson
from lp.registry.interfaces.product import IProduct
-class IPersonProduct(Interface):
+class IPersonProduct(IHasMergeProposals):
"""A person's view on a product."""
person = Reference(IPerson)
product = Reference(IProduct)
+ displayname = TextLine()
+
class IPersonProductFactory(Interface):
"""Creates `IPersonProduct`s."""
def create(person, product):
"""Create and return an `IPersonProduct`."""
-
=== modified file 'lib/lp/registry/model/personproduct.py'
--- lib/lp/registry/model/personproduct.py 2010-08-20 20:31:18 +0000
+++ lib/lp/registry/model/personproduct.py 2011-05-09 19:16:03 +0000
@@ -13,13 +13,16 @@
implements,
)
+from lp.code.model.hasbranches import (
+ HasMergeProposalsMixin,
+ )
from lp.registry.interfaces.personproduct import (
IPersonProduct,
IPersonProductFactory,
)
-class PersonProduct:
+class PersonProduct(HasMergeProposalsMixin):
implements(IPersonProduct)
@@ -32,3 +35,8 @@
@staticmethod
def create(person, product):
return PersonProduct(person, product)
+
+ @property
+ def displayname(self):
+ return '%s in %s' % (
+ self.person.displayname, self.product.displayname)