launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #11717
[Merge] lp:~sinzui/launchpad/affilliations-api into lp:launchpad
Curtis Hovey has proposed merging lp:~sinzui/launchpad/affilliations-api into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #185709 in Launchpad itself: "Being bug supervisor for project should associate team/user"
https://bugs.launchpad.net/launchpad/+bug/185709
For more details, see:
https://code.launchpad.net/~sinzui/launchpad/affilliations-api/+merge/123352
Show projects that the user is a bug supervisor for.
This branch intended to rename getOwnedOrDrivenPillars() to
getAffiliatedPillars() then export it. Exporting is more complicated
than I first thought. I cut scope while I discuss the right solution.
I did see an opportunity to fix the affiliated bug supervisor bug
while reviewing my options.
--------------------------------------------------------------------
RULES
Pre-implementation: no one
* Update getOwnedOrDrivePillars to search the distribution and
product bug_supervisor column.
* Rename getOwnedOrDrivenPillars() to getAffiliatedPillars()
ADDENDUM
* A view called getOwnedOrDrivenPillars() 5 times because the
the helper property was not cached.
QA
* Visit https://qastaging.launchpad.net/~sinzui/+related-projects
* Verify that "Launchpad Developer Utilities" is listed on the page.
LINT
Linting changed files:
lib/lp/registry/browser/person.py
lib/lp/registry/doc/person-account.txt
lib/lp/registry/doc/person.txt
lib/lp/registry/interfaces/person.py
lib/lp/registry/model/person.py
lib/lp/registry/tests/test_person.py
TEST
./bin/test -vvc -t getAffiliatedPillars -t person-account lp.registry.tests
IMPLEMENTATION
Renamed the method. I replaced the doc test with unit tests. I updated
the method to also query for bug_supervisor.
lib/lp/registry/doc/person-account.txt
lib/lp/registry/doc/person.txt
lib/lp/registry/interfaces/person.py
lib/lp/registry/model/person.py
lib/lp/registry/tests/test_person.py
I discovered that the method was called indirectly 5 times on some pages
because the private property was not cached.
lib/lp/registry/browser/person.py
--
https://code.launchpad.net/~sinzui/launchpad/affilliations-api/+merge/123352
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~sinzui/launchpad/affilliations-api into lp:launchpad.
=== modified file 'lib/lp/registry/browser/person.py'
--- lib/lp/registry/browser/person.py 2012-09-06 00:01:38 +0000
+++ lib/lp/registry/browser/person.py 2012-09-07 19:46:26 +0000
@@ -675,7 +675,7 @@
def projects(self):
target = '+related-projects'
text = 'Related projects'
- enabled = bool(self.person.getOwnedOrDrivenPillars())
+ enabled = bool(self.person.getAffiliatedPillars())
return Link(target, text, enabled=enabled, icon='info')
def subscriptions(self):
@@ -3598,9 +3598,10 @@
return self._tableHeaderMessage(
self.related_projects_count, label='project')
+ @cachedproperty
def _related_projects(self):
"""Return all projects owned or driven by this person."""
- return self.context.getOwnedOrDrivenPillars()
+ return self.context.getAffiliatedPillars()
def _tableHeaderMessage(self, count, label='package'):
"""Format a header message for the tables on the summary page."""
=== modified file 'lib/lp/registry/doc/person-account.txt'
--- lib/lp/registry/doc/person-account.txt 2012-08-07 02:31:56 +0000
+++ lib/lp/registry/doc/person-account.txt 2012-09-07 19:46:26 +0000
@@ -104,7 +104,7 @@
True
>>> foobar_pillars = []
- >>> for pillar_name in foobar.getOwnedOrDrivenPillars():
+ >>> for pillar_name in foobar.getAffiliatedPillars():
... pillar = pillar_name.pillar
... if pillar.owner == foobar or pillar.driver == foobar:
... foobar_pillars.append(pillar_name)
@@ -183,7 +183,7 @@
...no owned or driven pillars...
- >>> foobar.getOwnedOrDrivenPillars().count()
+ >>> foobar.getAffiliatedPillars().count()
0
...and, finally, to not be considered a valid person in Launchpad.
@@ -198,7 +198,7 @@
>>> from lp.app.interfaces.launchpad import ILaunchpadCelebrities
>>> registry_experts = getUtility(ILaunchpadCelebrities).registry_experts
- >>> registry_pillars = set(registry_experts.getOwnedOrDrivenPillars())
+ >>> registry_pillars = set(registry_experts.getAffiliatedPillars())
>>> registry_pillars.issuperset(foobar_pillars)
True
=== modified file 'lib/lp/registry/doc/person.txt'
--- lib/lp/registry/doc/person.txt 2012-08-07 02:31:56 +0000
+++ lib/lp/registry/doc/person.txt 2012-09-07 19:46:26 +0000
@@ -1031,48 +1031,6 @@
[u'mozilla-firefox', u'pmount']
-Pillars owned or driven by a person or team
--------------------------------------------
-
-To obtain all distributions, project groups and projects owned or driven
-by a person or team, we can use the getOwnedOrDrivenPillars() method of
-IPerson. This method returns PillarNames ordered by distribution,
-project groups and projects.
-
- >>> login(ANONYMOUS)
-
- >>> from lp.registry.interfaces.distribution import IDistribution
- >>> from lp.registry.interfaces.product import IProduct
- >>> from lp.registry.interfaces.projectgroup import IProjectGroup
-
- >>> def print_pillar(pillarname):
- ... pillar = pillarname.pillar
- ... if IDistribution.providedBy(pillar):
- ... pillar_type = 'distribution'
- ... elif IProjectGroup.providedBy(pillar):
- ... pillar_type = 'project group'
- ... elif IProduct.providedBy(pillar):
- ... pillar_type = 'project'
- ... print "%s: %s (%s)" % (
- ... pillar_type, pillar.displayname, pillar.name)
-
- >>> for pillarname in mark.getOwnedOrDrivenPillars():
- ... print_pillar(pillarname)
- distribution: Debian (debian)
- distribution: Gentoo (gentoo)
- distribution: Kubuntu (kubuntu)
- distribution: Red Hat (redhat)
- project group: Apache (apache)
- project: Derby (derby)
- project: alsa-utils (alsa-utils)
-
- >>> for pillarname in ubuntu_team.getOwnedOrDrivenPillars():
- ... print_pillar(pillarname)
- distribution: Ubuntu (ubuntu)
- distribution: ubuntutest (ubuntutest)
- project: Tomcat (tomcat)
-
-
Project owned by a person or team
---------------------------------
=== modified file 'lib/lp/registry/interfaces/person.py'
--- lib/lp/registry/interfaces/person.py 2012-08-21 04:28:11 +0000
+++ lib/lp/registry/interfaces/person.py 2012-09-07 19:46:26 +0000
@@ -1132,8 +1132,12 @@
the icons which represent that category.
"""
- def getOwnedOrDrivenPillars():
- """Return the pillars that this person directly owns or drives."""
+ def getAffiliatedPillars():
+ """Return the pillars that this person directly has a role with.
+
+ Returns distributions, project groups, and projects that this person
+ maintains, drives, or is the bug supervisor for.
+ """
def getOwnedProjects(match_name=None):
"""Projects owned by this person or teams to which she belongs.
=== modified file 'lib/lp/registry/model/person.py'
--- lib/lp/registry/model/person.py 2012-08-30 11:48:26 +0000
+++ lib/lp/registry/model/person.py 2012-09-07 19:46:26 +0000
@@ -1117,7 +1117,7 @@
cur.execute(query)
return cur.fetchall()
- def getOwnedOrDrivenPillars(self):
+ def getAffiliatedPillars(self):
"""See `IPerson`."""
find_spec = (PillarName, SQL('kind'), SQL('displayname'))
origin = SQL("""
@@ -1128,7 +1128,8 @@
WHERE
active = True AND
(driver = %(person)s
- OR owner = %(person)s)
+ OR owner = %(person)s
+ OR bug_supervisor = %(person)s)
UNION
SELECT name, 2 as kind, displayname
FROM project
@@ -1142,6 +1143,7 @@
WHERE
driver = %(person)s
OR owner = %(person)s
+ OR bug_supervisor = %(person)s
) _pillar
ON PillarName.name = _pillar.name
""" % sqlvalues(person=self))
@@ -2223,7 +2225,7 @@
registry_experts = getUtility(ILaunchpadCelebrities).registry_experts
for team in Person.selectBy(teamowner=self):
team.teamowner = registry_experts
- for pillar_name in self.getOwnedOrDrivenPillars():
+ for pillar_name in self.getAffiliatedPillars():
pillar = pillar_name.pillar
# XXX flacoste 2007-11-26 bug=164635 The comparison using id below
# works around a nasty intermittent failure.
=== modified file 'lib/lp/registry/tests/test_person.py'
--- lib/lp/registry/tests/test_person.py 2012-08-30 11:48:26 +0000
+++ lib/lp/registry/tests/test_person.py 2012-09-07 19:46:26 +0000
@@ -318,7 +318,37 @@
self.assertEqual(None, person.homepage_content)
self.assertEqual(None, person.teamdescription)
- def test_getOwnedOrDrivenPillars(self):
+ def test_getAffiliatedPillars_kinds(self):
+ # Distributions, project groups, and projects are returned in this
+ # same order.
+ user = self.factory.makePerson()
+ project = self.factory.makeProduct(owner=user)
+ project_group = self.factory.makeProject(owner=user)
+ distribution = self.factory.makeDistribution(owner=user)
+ expected_pillars = [
+ distribution.name, project_group.name, project.name]
+ received_pillars = [
+ pillar.name for pillar in user.getAffiliatedPillars()]
+ self.assertEqual(expected_pillars, received_pillars)
+
+ def test_getAffiliatedPillars_roles(self):
+ # owned, driven, and supervised pillars are returned ordered by
+ # display name.
+ user = self.factory.makePerson()
+ owned_project = self.factory.makeProduct(owner=user, name="cat")
+ driven_project = self.factory.makeProduct(name="bat")
+ supervised_project = self.factory.makeProduct(name='nat')
+ with celebrity_logged_in('admin'):
+ driven_project.driver = user
+ supervised_project.bug_supervisor = user
+ expected_pillars = [
+ driven_project.name, owned_project.name, supervised_project.name]
+ received_pillars = [
+ pillar.name for pillar in user.getAffiliatedPillars()]
+ self.assertEqual(expected_pillars, received_pillars)
+
+ def test_getAffiliatedPillars_active_pillars(self):
+ # Only active pillars are returned.
user = self.factory.makePerson()
active_project = self.factory.makeProject(owner=user)
inactive_project = self.factory.makeProject(owner=user)
@@ -326,7 +356,7 @@
inactive_project.active = False
expected_pillars = [active_project.name]
received_pillars = [pillar.name for pillar in
- user.getOwnedOrDrivenPillars()]
+ user.getAffiliatedPillars()]
self.assertEqual(expected_pillars, received_pillars)
def test_no_merge_pending(self):
Follow ups