Thanks for taking on another interesting bug to fix. Thanks also for the additional test.
I did you a bit of a disservice by not doing a full review earlier. Now that I have I've discovered a few more things that need fixing and yet another test that needs to be added. But I'm confident with these additions the branch will be ready to land, at least from a code perspective. Recall you need to get beuno or noodles to do a UI review.
The way you've made this change does not allow the new parameter to be
used via the webservice/launchpadlib. Look at the paste I've included
at the bottom for changes which will export the new parameter. You'll
need to do a 'make clean build' to ensure the wadl gets rebuilt.
A test in registry/webservices/xx-person.txt will be needed to show
that the silent param works from the web service and that it only
works for admins.
You can also exercise it interactively using launchpadlib. Here's a
transcript to get you started:
% bin/ipy
In [1]: from launchpadlib.launchpad import Launchpad
In [2]: lp = Launchpad.login_with('interactive', 'dev')
In [3]: salgado = lp.people['salgado']
In [4]: salgado_ls = list(salgado.memberships_details)[1]
In [5]: salgado_ls.setStatus(status='Deactivated', silent=False)
In [6]: salgado_ls.setStatus(status='Deactivated', silent=True)
If you have your mailer set up properly you'll even get the email when
generated.
> The user and comment are stored in last_changed_by and
> === modified file 'lib/lp/registry/model/teammembership.py'
> --- lib/lp/registry/model/teammembership.py 2009-06-25 04:06:00 +0000
> +++ lib/lp/registry/model/teammembership.py 2009-12-16 10:19:15 +0000
> @@ -165,6 +165,14 @@
> template % replacements, force_wrap=True)
> simple_sendmail(from_addr, address, subject, msg)
>
> + def canChangeStatusSilently(self, user):
> + """Ensure that the user is in the Launchpad Administrators group before
> + silently making changes to their membership status."""
> + if user.inTeam(getUtility(ILaunchpadCelebrities).admin):
> + return True
> + else:
> + return False
Hi Jonathan,
Thanks for taking on another interesting bug to fix. Thanks also for the additional test.
I did you a bit of a disservice by not doing a full review earlier. Now that I have I've discovered a few more things that need fixing and yet another test that needs to be added. But I'm confident with these additions the branch will be ready to land, at least from a code perspective. Recall you need to get beuno or noodles to do a UI review.
> === modified file 'lib/lp/ registry/ browser/ teammembership. py' registry/ browser/ teammembership. py 2009-10-07 21:54:20 +0000 registry/ browser/ teammembership. py 2009-12-16 10:19:15 +0000 setExpirationDa te(expires, self.user)
> --- lib/lp/
+++ lib/lp/
> @@ -303,7 +303,8 @@
>
> self.context.
The silent param is a boolean, so rather than relying on the form to
return True, False, or None do the following:
silent = self.request. form.get( 'silent' , False)
and then use that value in the call to setStatus.
> self.context. setStatus( form_ng. getOne( 'comment' )) form_ng. getOne( 'comment' ), form.get( 'silent' )) ate(self) :
> - status, self.user, self.request.
> + status, self.user, self.request.
> + self.request.
> return True
>
> def _getExpirationD
> === modified file 'lib/lp/ registry/ doc/teammembers hip-email- notification. txt' registry/ doc/teammembers hip-email- notification. txt 2009-08-24 03:01:12 +0000 registry/ doc/teammembers hip-email- notification. txt 2009-12-16 10:19:15 +0000 membership, status, reviewer=None, comment=None): membership, status, reviewer=None, comment=None,
> --- lib/lp/
> +++ lib/lp/
> @@ -9,14 +9,16 @@
> >>> def by_to_addrs(a, b):
> ... return cmp(a[1], b[1])
>
> - >>> def setStatus(
> + >>> def setStatus(
> + ... silent=False):
I think we have the choice to indent by 4 or line up after the opening
paren here. I prefer the latter.
> ... """Set the status of the given membership. updates setStatus( status, reviewer, comment=comment) setStatus( status, reviewer, comment=comment, updates( ) commit( ) admins_ membership = membershipset. getByPersonAndT eam( mirror_ admins_ membership, TeamMembershipS tatus.DEACTIVAT ED, test_emails) launchpad. dev/~ubuntu- team> ------- ------- ------- ------- ----- IPersonSet) .getByName( 'thumper' ) getByName( 'hwdb-team' ) hwdb_membership = membershipset. getByPersonAndT eam(thumper, hwdb_membership .status. title thumper_ hwdb_membership , tatus.DEACTIVAT ED, reviewer=mark, silent=True) test_emails) hwdb_membership .status. title
> ...
> ... Also sets the reviewer and comment, calling flush_database_
> ... and transaction.commit after, to ensure the changes are flushed to
> ... the database.
> ... """
> - ... membership.
> + ... membership.
> + ... silent=silent)
> ... flush_database_
> ... transaction.
>
> @@ -780,7 +782,7 @@
> >>> mirror_
> ... mirror_admins, ubuntu_team)
> >>> setStatus(
> - ... reviewer=mark)
> + ... reviewer=mark, silent=False)
> >>> len(stub.
> 6
>
> @@ -797,6 +799,21 @@
> <http://
> -------
>
> +Deactivating memberships can also be done silently (no email notifications
> +sent) by Launchpad Administrators.
> +
> + >>> thumper = getUtility(
> + >>> hwdb_admins = personset.
> + >>> thumper_
> + ... hwdb_admins)
> + >>> print thumper_
> + Approved
> + >>> setStatus(
> + ... TeamMembershipS
> + >>> len(stub.
> + 0
> + >>> print thumper_
> + Deactivated
Nice new test!
> Joining a team with a mailing list ------- ------- ------- ------
> -------
> === modified file 'lib/lp/ registry/ interfaces/ teammembership. py' registry/ interfaces/ teammembership. py 2009-06-25 04:06:00 +0000 registry/ interfaces/ teammembership. py 2009-12-16 10:19:15 +0000 copy_field( status) , copy_field( reviewer_ comment) ) write_operation ()
> --- lib/lp/
> +++ lib/lp/
> @@ -214,7 +214,7 @@
> status=
> comment=
> @export_
> - def setStatus(status, user, comment=None):
> + def setStatus(status, user, comment=None, silent=False):
> """Set the status of this membership.
The way you've made this change does not allow the new parameter to be launchpadlib. Look at the paste I've included
used via the webservice/
at the bottom for changes which will export the new parameter. You'll
need to do a 'make clean build' to ensure the wadl gets rebuilt.
A test in registry/ webservices/ xx-person. txt will be needed to show
that the silent param works from the web service and that it only
works for admins.
You can also exercise it interactively using launchpadlib. Here's a
transcript to get you started:
% bin/ipy launchpad import Launchpad login_with( 'interactive' , 'dev') 'salgado' ] memberships_ details) [1] ls.setStatus( status= 'Deactivated' , silent=False) ls.setStatus( status= 'Deactivated' , silent=True)
In [1]: from launchpadlib.
In [2]: lp = Launchpad.
In [3]: salgado = lp.people[
In [4]: salgado_ls = list(salgado.
In [5]: salgado_
In [6]: salgado_
If you have your mailer set up properly you'll even get the email when
generated.
> The user and comment are stored in last_changed_by and
> === modified file 'lib/lp/ registry/ model/teammembe rship.py' registry/ model/teammembe rship.py 2009-06-25 04:06:00 +0000 registry/ model/teammembe rship.py 2009-12-16 10:19:15 +0000 sendmail( from_addr, address, subject, msg) Silently( self, user): getUtility( ILaunchpadCeleb rities) .admin) :
> --- lib/lp/
> +++ lib/lp/
> @@ -165,6 +165,14 @@
> template % replacements, force_wrap=True)
> simple_
>
> + def canChangeStatus
> + """Ensure that the user is in the Launchpad Administrators group before
> + silently making changes to their membership status."""
> + if user.inTeam(
> + return True
> + else:
> + return False
Simplify to:
> + return user.inTeam( getUtility( ILaunchpadCeleb rities) .admin
> def canChangeExpira tionDate( self, person): p`.""" getAdministrate dTeams( ) canonical. noreply_ from_address) sendmail( from_addr, to_addrs, subject, msg) p`.""" tatusSilently( user), ( tatus.APPROVED tatus.ADMIN tatus.EXPIRED changed_ by and self.status == proposed: sChangeNotifica tion(old_ status) sChangeNotifica tion(old_ status) geNotification( self, old_status):
> """See `ITeamMembershi
> person_is_admin = self.team in person.
> @@ -269,11 +277,15 @@
> team.displayname, config.
> simple_
>
> - def setStatus(self, status, user, comment=None):
> + def setStatus(self, status, user, comment=None, silent=False):
> """See `ITeamMembershi
> if status == self.status:
> return
>
> + if silent:
> + assert self.canChangeS
> + "You may not change user's membership statuses silently.")
> +
> approved = TeamMembershipS
> admin = TeamMembershipS
> expired = TeamMembershipS
> @@ -360,7 +372,8 @@
> if self.person == self.last_
> return
>
> - self._sendStatu
> + if not silent:
> + self._sendStatu
>
> def _sendStatusChan
> """Send a status change notification to all team admins and the
> === modified file 'lib/lp/ registry/ templates/ teammembership- index.pt' registry/ templates/ teammembership- index.pt 2009-12-03 18:33:22 +0000 registry/ templates/ teammembership- index.pt 2009-12-16 10:19:15 +0000 "template/ macros/ comment" /> "context/ required: launchpad. Admin">
> --- lib/lp/
> +++ lib/lp/
> @@ -140,6 +140,13 @@
>
> <metal:comment use-macro=
>
> + <tr tal:condition=
> + <th>Silent:</th>
> + <td>
> + <input type="checkbox" value="no" name="silent" id="silent" />
> + </td>
> + </tr>
The <th> and <td> should be indented only 2 spaces.
I don't like the use of "silent" in the UI. I suspect the UI reviewer
might comment on that.
In the attached paste I have some changes to the template to add some
explanatory text to the checkbox and to augment the explanation for
the comment.
> <tr>
> <th />
> <td>
Please see this paste for suggested changes:
http:// pastebin. ubuntu. com/342934/