launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #25093
[Merge] ~twom/launchpad:text-types-in-registry-xmlrpc into launchpad:master
Tom Wardill has proposed merging ~twom/launchpad:text-types-in-registry-xmlrpc into launchpad:master.
Commit message:
Fix mailinglist XMLRPC callsites for text types
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~twom/launchpad/+git/launchpad/+merge/388121
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~twom/launchpad:text-types-in-registry-xmlrpc into launchpad:master.
diff --git a/lib/lp/registry/tests/test_xmlrpc.py b/lib/lp/registry/tests/test_xmlrpc.py
index 5217f8c..79bf7f8 100644
--- a/lib/lp/registry/tests/test_xmlrpc.py
+++ b/lib/lp/registry/tests/test_xmlrpc.py
@@ -5,12 +5,35 @@
__metaclass__ = type
+from email import message_from_string
+from textwrap import dedent
+
from six.moves import xmlrpc_client
+from zope.component import getUtility
from zope.security.proxy import removeSecurityProxy
-from lp.registry.enums import PersonVisibility
-from lp.testing import TestCaseWithFactory
-from lp.testing.layers import DatabaseFunctionalLayer
+from lp.registry.enums import (
+ PersonVisibility,
+ TeamMembershipPolicy,
+ )
+from lp.registry.interfaces.mailinglist import (
+ IMailingListSet,
+ IMessageApprovalSet,
+ MailingListStatus,
+ PostedMessageStatus,
+ )
+from lp.registry.interfaces.person import PersonalStanding
+from lp.services.config import config
+from lp.testing import (
+ admin_logged_in,
+ person_logged_in,
+ TestCaseWithFactory,
+ )
+from lp.testing.layers import (
+ DatabaseFunctionalLayer,
+ LaunchpadFunctionalLayer,
+ )
+from lp.testing.mail_helpers import pop_notifications
from lp.testing.xmlrpc import XMLRPCTestTransport
@@ -58,3 +81,130 @@ class TestCanonicalSSOApplication(TestCaseWithFactory):
public_rpc_proxy.getPersonDetailsByOpenIDIdentifier,
openid_identifier)
self.assertEqual(404, e.errcode)
+
+
+class TestMailingListXMLRPC(TestCaseWithFactory):
+
+ layer = DatabaseFunctionalLayer
+
+ def setUp(self):
+ super(TestMailingListXMLRPC, self).setUp()
+ self.rpc_proxy = xmlrpc_client.ServerProxy(
+ 'http://xmlrpc-private.launchpad.test:8087/mailinglists',
+ transport=XMLRPCTestTransport())
+
+ def test_getMembershipInformation(self):
+ team, member = self.factory.makeTeamWithMailingListSubscribers(
+ 'team', auto_subscribe=False)
+ result = self.rpc_proxy.getMembershipInformation(
+ [team.name])
+ self.assertIn(team.name, result.keys())
+
+ def test_reportStatus(self):
+ # Successful constructions lead to ACTIVE lists.
+ team = self.factory.makeTeam(name='team')
+ team_list = getUtility(IMailingListSet).new(team, team.teamowner)
+ self.rpc_proxy.getPendingActions()
+ self.rpc_proxy.reportStatus({'team': 'success'})
+ self.assertEqual(MailingListStatus.ACTIVE, team_list.status)
+
+ def test_isTeamPublic(self):
+ self.factory.makeTeam(
+ name='team-a', visibility=PersonVisibility.PUBLIC)
+ self.factory.makeTeam(
+ name='team-b', visibility=PersonVisibility.PRIVATE)
+ self.assertIs(True, self.rpc_proxy.isTeamPublic('team-a'))
+ self.assertIs(False, self.rpc_proxy.isTeamPublic('team-b'))
+
+ def test_isRegisteredInLaunchpad(self):
+ self.factory.makeTeam(email='me@xxxxxxxxx')
+ self.assertFalse(
+ self.rpc_proxy.isRegisteredInLaunchpad('me@xxxxxxxxx'))
+
+ def test_inGoodStanding(self):
+ self.factory.makePerson(email='no@xxxxxx')
+ yes_person = self.factory.makePerson(email='yes@xxxxxx')
+ with admin_logged_in():
+ yes_person.personal_standing = PersonalStanding.GOOD
+ self.assertIs(True, self.rpc_proxy.inGoodStanding('yes@xxxxxx'))
+ self.assertIs(False, self.rpc_proxy.inGoodStanding('no@xxxxxx'))
+
+ def test_updateTeamAddresses(self):
+ staging_config_name = self.factory.getUniqueString()
+ config.push(
+ staging_config_name,
+ '\n[launchpad]\nis_demo: True\n'
+ '\n[mailman]\nbuild_host_name: lists.launchpad.test\n')
+ try:
+ self.rpc_proxy.updateTeamAddresses('lists.launchpad.net')
+ finally:
+ config.pop(staging_config_name)
+
+
+
+class TestMailingListXMLRPCMessage(TestCaseWithFactory):
+
+ layer = LaunchpadFunctionalLayer
+
+ def setUp(self):
+ super(TestMailingListXMLRPCMessage, self).setUp()
+ self.rpc_proxy = xmlrpc_client.ServerProxy(
+ 'http://xmlrpc-private.launchpad.test:8087/mailinglists',
+ transport=XMLRPCTestTransport())
+
+ def makeMailingListAndHeldMessage(self, private=False):
+ if private:
+ visibility = PersonVisibility.PRIVATE
+ else:
+ visibility = PersonVisibility.PUBLIC
+ owner = self.factory.makePerson()
+ team = self.factory.makeTeam(
+ name='team', owner=owner, visibility=visibility,
+ membership_policy=TeamMembershipPolicy.RESTRICTED)
+ with person_logged_in(owner):
+ self.factory.makeMailingList(team, owner)
+ sender = self.factory.makePerson(email='me@xxxxxx')
+ with person_logged_in(sender):
+ message = message_from_string(dedent("""\
+ From: me@xxxxxx
+ To: team@xxxxxxxxxxxxxxxxxxxx
+ Subject: A question
+ Message-ID: <first-post>
+ Date: Fri, 01 Aug 2000 01:08:59 -0000\n
+ I have a question about this team.
+ """))
+ return team, sender, message
+
+ def test_holdMessage(self):
+ # Calling holdMessages send a copy of the message text to Lp
+ # and notifies a team admins to moderate it.
+ team, sender, message = self.makeMailingListAndHeldMessage()
+ pop_notifications()
+ info = self.rpc_proxy.holdMessage('team', message.as_string())
+ notifications = pop_notifications()
+ found = getUtility(IMessageApprovalSet).getMessageByMessageID(
+ '<first-post>')
+ self.assertIs(True, info)
+ self.assertIsNot(None, found)
+ self.assertEqual(1, len(notifications))
+ self.assertEqual(
+ 'New mailing list message requiring approval for Team',
+ notifications[0]['subject'])
+ self.assertTextMatchesExpressionIgnoreWhitespace(
+ '.*http://launchpad.test/~team/\+mailinglist-moderate.*',
+ notifications[0].get_payload())
+ self.assertEqual({}, self.rpc_proxy.getMessageDispositions())
+
+ def test_getMessageDispositions_accept(self):
+ # List moderators can approve messages.
+ team, sender, message = self.makeMailingListAndHeldMessage()
+ pop_notifications()
+ self.rpc_proxy.holdMessage('team', message.as_string())
+ found = getUtility(IMessageApprovalSet).getMessageByMessageID(
+ '<first-post>')
+ found.approve(team.teamowner)
+ self.assertEqual(PostedMessageStatus.APPROVAL_PENDING, found.status)
+ self.assertEqual(
+ {'<first-post>': ['team', 'accept']},
+ self.rpc_proxy.getMessageDispositions())
+ self.assertEqual(PostedMessageStatus.APPROVED, found.status)
diff --git a/lib/lp/registry/xmlrpc/mailinglist.py b/lib/lp/registry/xmlrpc/mailinglist.py
index 9a16123..6467dd5 100644
--- a/lib/lp/registry/xmlrpc/mailinglist.py
+++ b/lib/lp/registry/xmlrpc/mailinglist.py
@@ -10,6 +10,7 @@ __all__ = [
import re
+from six import ensure_text
from six.moves import xmlrpc_client
from zope.component import getUtility
from zope.interface import implementer
@@ -106,6 +107,7 @@ class MailingListAPIView(LaunchpadXMLRPCView):
"""See `IMailingListAPIView`."""
list_set = getUtility(IMailingListSet)
for team_name, action_status in statuses.items():
+ team_name = ensure_text(team_name)
mailing_list = list_set.get(team_name)
if mailing_list is None:
return faults.NoSuchTeamMailingList(team_name)
@@ -136,6 +138,7 @@ class MailingListAPIView(LaunchpadXMLRPCView):
def getMembershipInformation(self, teams):
"""See `IMailingListAPIView`."""
+ teams = [ensure_text(team) for team in teams]
mailing_list_set = getUtility(IMailingListSet)
response = {}
# There are two sets of email addresses we need. The first is the set
@@ -243,6 +246,7 @@ class MailingListAPIView(LaunchpadXMLRPCView):
# pass 8-bit strings.
if isinstance(bytes, xmlrpc_client.Binary):
bytes = bytes.data
+ team_name = ensure_text(team_name)
# Although it is illegal for an email header to have unencoded
# non-ascii characters, it is better to let the list owner
# process the message than to cause an oops.