Merge lp:~sinzui/launchpad/retract-membership-0 into lp:launchpad

Proposed by Curtis Hovey
Status: Merged
Merged at revision: 11962
Proposed branch: lp:~sinzui/launchpad/retract-membership-0
Merge into: lp:launchpad
Diff against target: 59 lines (+21/-3)
2 files modified
lib/lp/registry/interfaces/person.py (+9/-3)
lib/lp/registry/stories/webservice/xx-person.txt (+12/-0)
To merge this branch: bzr merge lp:~sinzui/launchpad/retract-membership-0
Reviewer Review Type Date Requested Status
Edwin Grubbs (community) code Approve
Review via email: mp+41511@code.launchpad.net

Description of the change

This is my branch to allow team admins to remove their team from another team
via an API call.

    lp:~sinzui/launchpad/retract-membership-0
    Diff size: 47
    Launchpad bug: https://bugs.launchpad.net/bugs/680152
    Test command: ./bin/test -vv -t webservice/xx-person.txt
    Pre-implementation: abentley, leonardr
    Target release: 10.12

Allow team admins to remove their team from another team via an API call
------------------------------------------------------------------------

Team admins can accept or decline the invitation to join a team, but
they cannot retract an accepted invitation. The only way a team can
leave another team is by the the admin of the subteam requesting an admin
of the superteam to do the removal. Team admins, like users, should have
the power to retract their memberships.

Rules
-----

    * Export retractTeamMembership over the API.

QA
--

# This script tests that a team admin can remove his team from it's
# super teams.
from launchpadlib.launchpad import Launchpad STAGING_SERVICE_ROOT

def retract_registry_memberships():
    lp = Launchpad.login_with('testing', STAGING_SERVICE_ROOT)
    my_team = lp.people['registry']
    for super_team in my_team.teams_participated_in:
        print "Removing %s from %s" % (my_team.name, super_team.name)
        try:
            my_team.retractTeamMembership(team=super_team)
        except:
            pass

if __name__ == '__main__':
    retract_registry_memberships()

Lint
----

Linting changed files:
  lib/lp/registry/interfaces/person.py
  lib/lp/registry/stories/webservice/xx-person.txt

There are indentation and header issues in the test that I can fix after the
review.

To post a comment you must log in.
Revision history for this message
Edwin Grubbs (edwin-grubbs) wrote :

Hi Curtis,

This branch looks good. I just have one comment below.

-Edwin

>=== modified file 'lib/lp/registry/interfaces/person.py'
>--- lib/lp/registry/interfaces/person.py 2010-11-18 12:05:34 +0000
>+++ lib/lp/registry/interfaces/person.py 2010-11-22 22:14:01 +0000
>@@ -1075,10 +1075,10 @@
> since it inherits from `IPerson`) is a member of himself
> (i.e. `person1.inTeam(person1)`).
>
>- :param team: One of an object providing `IPerson`, the string name of a
>- team or `None`. If a string was supplied the team is looked up.
>+ :param team: One of an object providing `IPerson`, the string name of
>+ a team or `None`. If a string was supplied the team is looked up.

I think "One of" should be rewritten either as "One of the following:"
or just "Either".

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/registry/interfaces/person.py'
2--- lib/lp/registry/interfaces/person.py 2010-11-18 12:05:34 +0000
3+++ lib/lp/registry/interfaces/person.py 2010-11-22 23:11:44 +0000
4@@ -1075,10 +1075,10 @@
5 since it inherits from `IPerson`) is a member of himself
6 (i.e. `person1.inTeam(person1)`).
7
8- :param team: One of an object providing `IPerson`, the string name of a
9- team or `None`. If a string was supplied the team is looked up.
10+ :param team: Either an object providing `IPerson`, the string name of
11+ a team or `None`. If a string was supplied the team is looked up.
12 :return: A bool with the result of the membership lookup. When looking
13- up the team from a string finds nothing or team was `None` then
14+ up the team from a string finds nothing or team was `None` then
15 `False` is returned.
16 """
17
18@@ -1551,6 +1551,11 @@
19 to INVITATION_DECLINED.
20 """
21
22+ @call_with(user=REQUEST_USER)
23+ @operation_parameters(
24+ team=copy_field(ITeamMembership['team']),
25+ comment=Text(required=False))
26+ @export_write_operation()
27 def retractTeamMembership(team, user, comment=None):
28 """Retract this team's membership in the given team.
29
30@@ -2238,6 +2243,7 @@
31 (IPersonEditRestricted['addMember'], 'person'),
32 (IPersonEditRestricted['acceptInvitationToBeMemberOf'], 'team'),
33 (IPersonEditRestricted['declineInvitationToBeMemberOf'], 'team'),
34+ (IPersonEditRestricted['retractTeamMembership'], 'team'),
35 ]
36 for method, name in params_to_fix:
37 method.queryTaggedValue(
38
39=== modified file 'lib/lp/registry/stories/webservice/xx-person.txt'
40--- lib/lp/registry/stories/webservice/xx-person.txt 2010-10-18 22:24:59 +0000
41+++ lib/lp/registry/stories/webservice/xx-person.txt 2010-11-22 23:11:44 +0000
42@@ -749,6 +749,18 @@
43 >>> webservice.get("/~ubuntu-team/+member/name20").jsonBody()['status']
44 u'Invitation declined'
45
46+The retractTeamMembership method allows a team admin to remove his team from
47+another team.
48+
49+ >>> print webservice.named_post(
50+ ... landscape_developers['self_link'], 'retractTeamMembership',
51+ ... {}, team=ubuntu_team['self_link'], comment='bye bye')
52+ HTTP/1.1 200 Ok
53+ ...
54+ >>> webservice.get("/~ubuntu-team/+member/landscape-developers"
55+ ... ).jsonBody()['status']
56+ u'Deactivated'
57+
58 To check whether or not a given person is a participant in a team, use the
59 'inTeam' custom operation.
60