launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #16542
[Merge] lp:~wgrant/launchpad/getOwnedProjects into lp:launchpad
William Grant has proposed merging lp:~wgrant/launchpad/getOwnedProjects into lp:launchpad.
Commit message:
Extend and export IPerson.getOwnedProjects like getOwnedTeams, so scripts can audit the full ownership hierarchy of important global objects.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~wgrant/launchpad/getOwnedProjects/+merge/210375
Extend and export IPerson.getOwnedProjects like getOwnedTeams, so scripts can audit the full ownership hierarchy of important global objects.
--
https://code.launchpad.net/~wgrant/launchpad/getOwnedProjects/+merge/210375
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/getOwnedProjects into lp:launchpad.
=== modified file 'lib/lp/_schema_circular_imports.py'
--- lib/lp/_schema_circular_imports.py 2014-03-07 01:20:34 +0000
+++ lib/lp/_schema_circular_imports.py 2014-03-11 10:35:14 +0000
@@ -355,6 +355,7 @@
patch_collection_return_type(
IPerson, 'getArchiveSubscriptions', IArchiveSubscriber)
patch_entry_return_type(IPerson, 'getRecipe', ISourcePackageRecipe)
+patch_collection_return_type(IPerson, 'getOwnedProjects', IProduct)
# IHasRecipe
patch_collection_property(
=== modified file 'lib/lp/registry/doc/person.txt'
--- lib/lp/registry/doc/person.txt 2013-08-08 04:11:59 +0000
+++ lib/lp/registry/doc/person.txt 2014-03-11 10:35:14 +0000
@@ -1064,6 +1064,13 @@
>>> for project in mark.getOwnedProjects():
... print project.displayname
Derby
+ alsa-utils
+
+We can also ask for projects owned through team memberships.
+
+ >>> for project in mark.getOwnedProjects(transitive=True):
+ ... print project.displayname
+ Derby
Tomcat
alsa-utils
@@ -1079,7 +1086,7 @@
>>> ignored = login_person(registry_member)
>>> derby = getUtility(IProductSet).getByName('derby')
>>> derby.active = False
- >>> for project in mark.getOwnedProjects():
+ >>> for project in mark.getOwnedProjects(transitive=True):
... print project.displayname
Tomcat
alsa-utils
@@ -1096,7 +1103,8 @@
The results returned can be filtered by providing a token to refine the
search.
- >>> for project in mark.getOwnedProjects(match_name=u'java'):
+ >>> for project in mark.getOwnedProjects(
+ ... match_name=u'java', transitive=True):
... print project.displayname
Tomcat
=== modified file 'lib/lp/registry/interfaces/person.py'
--- lib/lp/registry/interfaces/person.py 2014-03-11 06:10:53 +0000
+++ lib/lp/registry/interfaces/person.py 2014-03-11 10:35:14 +0000
@@ -1160,7 +1160,11 @@
maintains, drives, or is the bug supervisor for.
"""
- def getOwnedProjects(match_name=None):
+ @call_with(user=REQUEST_USER)
+ @operation_returns_collection_of(Interface) # Really IProduct.
+ @export_read_operation()
+ @operation_for_version("devel")
+ def getOwnedProjects(match_name=None, transitive=False, user=None):
"""Projects owned by this person or teams to which she belongs.
:param match_name: string optional project name to screen the results.
=== modified file 'lib/lp/registry/model/person.py'
--- lib/lp/registry/model/person.py 2014-03-11 06:10:53 +0000
+++ lib/lp/registry/model/person.py 2014-03-11 10:35:14 +0000
@@ -1103,17 +1103,29 @@
return DecoratedResultSet(results, get_pillar_name)
- def getOwnedProjects(self, match_name=None):
+ def getOwnedProjects(self, match_name=None, transitive=False, user=None):
"""See `IPerson`."""
# Import here to work around a circular import problem.
- from lp.registry.model.product import Product
+ from lp.registry.model.product import (
+ Product,
+ ProductSet,
+ )
clauses = [
Product.active == True,
- Product._ownerID == TeamParticipation.teamID,
- TeamParticipation.person == self,
]
+ if transitive:
+ # getProductPrivacyFilter may also use TeamParticipation, so
+ # ensure we use a different one.
+ ownership_participation = ClassAlias(TeamParticipation)
+ clauses.extend([
+ Product._ownerID == ownership_participation.teamID,
+ ownership_participation.person == self,
+ ])
+ else:
+ clauses.append(Product._ownerID == self.id)
+
# We only want to use the extra query if match_name is not None and it
# is not the empty string ('' or u'').
if match_name:
@@ -1122,6 +1134,10 @@
Product.name.contains_string(match_name),
Product.displayname.contains_string(match_name),
fti_search(Product, match_name)))
+
+ if user is not None:
+ clauses.append(ProductSet.getProductPrivacyFilter(user))
+
return IStore(Product).find(
Product, *clauses
).config(distinct=True).order_by(Product.displayname)
=== modified file 'lib/lp/registry/vocabularies.py'
--- lib/lp/registry/vocabularies.py 2014-01-07 14:02:51 +0000
+++ lib/lp/registry/vocabularies.py 2014-03-11 10:35:14 +0000
@@ -1438,7 +1438,7 @@
if self.is_commercial_admin:
projects = self.product_set.search(user, query)
else:
- projects = user.getOwnedProjects(match_name=query)
+ projects = user.getOwnedProjects(match_name=query, transitive=True)
return projects
def toTerm(self, project):