Merge ~twom/launchpad:text-types-in-registry-xmlrpc into launchpad:master

Proposed by Tom Wardill
Status: Merged
Approved by: Tom Wardill
Approved revision: 66a17aa8245722c9e288f492b3c7c3b5e1a8795b
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~twom/launchpad:text-types-in-registry-xmlrpc
Merge into: launchpad:master
Diff against target: 210 lines (+157/-3)
2 files modified
lib/lp/registry/tests/test_xmlrpc.py (+153/-3)
lib/lp/registry/xmlrpc/mailinglist.py (+4/-0)
Reviewer Review Type Date Requested Status
Colin Watson (community) Approve
Review via email: mp+388121@code.launchpad.net

Commit message

Fix mailinglist XMLRPC callsites for text types

To post a comment you must log in.
Revision history for this message
Colin Watson (cjwatson) wrote :

Thanks for fixing up my mistake.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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 @@
55
6__metaclass__ = type6__metaclass__ = type
77
8from email import message_from_string
9from textwrap import dedent
10
8from six.moves import xmlrpc_client11from six.moves import xmlrpc_client
12from zope.component import getUtility
9from zope.security.proxy import removeSecurityProxy13from zope.security.proxy import removeSecurityProxy
1014
11from lp.registry.enums import PersonVisibility15from lp.registry.enums import (
12from lp.testing import TestCaseWithFactory16 PersonVisibility,
13from lp.testing.layers import DatabaseFunctionalLayer17 TeamMembershipPolicy,
18 )
19from lp.registry.interfaces.mailinglist import (
20 IMailingListSet,
21 IMessageApprovalSet,
22 MailingListStatus,
23 PostedMessageStatus,
24 )
25from lp.registry.interfaces.person import PersonalStanding
26from lp.services.config import config
27from lp.testing import (
28 admin_logged_in,
29 person_logged_in,
30 TestCaseWithFactory,
31 )
32from lp.testing.layers import (
33 DatabaseFunctionalLayer,
34 LaunchpadFunctionalLayer,
35 )
36from lp.testing.mail_helpers import pop_notifications
14from lp.testing.xmlrpc import XMLRPCTestTransport37from lp.testing.xmlrpc import XMLRPCTestTransport
1538
1639
@@ -58,3 +81,130 @@ class TestCanonicalSSOApplication(TestCaseWithFactory):
58 public_rpc_proxy.getPersonDetailsByOpenIDIdentifier,81 public_rpc_proxy.getPersonDetailsByOpenIDIdentifier,
59 openid_identifier)82 openid_identifier)
60 self.assertEqual(404, e.errcode)83 self.assertEqual(404, e.errcode)
84
85
86class TestMailingListXMLRPC(TestCaseWithFactory):
87
88 layer = DatabaseFunctionalLayer
89
90 def setUp(self):
91 super(TestMailingListXMLRPC, self).setUp()
92 self.rpc_proxy = xmlrpc_client.ServerProxy(
93 'http://xmlrpc-private.launchpad.test:8087/mailinglists',
94 transport=XMLRPCTestTransport())
95
96 def test_getMembershipInformation(self):
97 team, member = self.factory.makeTeamWithMailingListSubscribers(
98 'team', auto_subscribe=False)
99 result = self.rpc_proxy.getMembershipInformation(
100 [team.name])
101 self.assertIn(team.name, result.keys())
102
103 def test_reportStatus(self):
104 # Successful constructions lead to ACTIVE lists.
105 team = self.factory.makeTeam(name='team')
106 team_list = getUtility(IMailingListSet).new(team, team.teamowner)
107 self.rpc_proxy.getPendingActions()
108 self.rpc_proxy.reportStatus({'team': 'success'})
109 self.assertEqual(MailingListStatus.ACTIVE, team_list.status)
110
111 def test_isTeamPublic(self):
112 self.factory.makeTeam(
113 name='team-a', visibility=PersonVisibility.PUBLIC)
114 self.factory.makeTeam(
115 name='team-b', visibility=PersonVisibility.PRIVATE)
116 self.assertIs(True, self.rpc_proxy.isTeamPublic('team-a'))
117 self.assertIs(False, self.rpc_proxy.isTeamPublic('team-b'))
118
119 def test_isRegisteredInLaunchpad(self):
120 self.factory.makeTeam(email='me@fndor.dom')
121 self.assertFalse(
122 self.rpc_proxy.isRegisteredInLaunchpad('me@fndor.dom'))
123
124 def test_inGoodStanding(self):
125 self.factory.makePerson(email='no@eg.dom')
126 yes_person = self.factory.makePerson(email='yes@eg.dom')
127 with admin_logged_in():
128 yes_person.personal_standing = PersonalStanding.GOOD
129 self.assertIs(True, self.rpc_proxy.inGoodStanding('yes@eg.dom'))
130 self.assertIs(False, self.rpc_proxy.inGoodStanding('no@eg.dom'))
131
132 def test_updateTeamAddresses(self):
133 staging_config_name = self.factory.getUniqueString()
134 config.push(
135 staging_config_name,
136 '\n[launchpad]\nis_demo: True\n'
137 '\n[mailman]\nbuild_host_name: lists.launchpad.test\n')
138 try:
139 self.rpc_proxy.updateTeamAddresses('lists.launchpad.net')
140 finally:
141 config.pop(staging_config_name)
142
143
144
145class TestMailingListXMLRPCMessage(TestCaseWithFactory):
146
147 layer = LaunchpadFunctionalLayer
148
149 def setUp(self):
150 super(TestMailingListXMLRPCMessage, self).setUp()
151 self.rpc_proxy = xmlrpc_client.ServerProxy(
152 'http://xmlrpc-private.launchpad.test:8087/mailinglists',
153 transport=XMLRPCTestTransport())
154
155 def makeMailingListAndHeldMessage(self, private=False):
156 if private:
157 visibility = PersonVisibility.PRIVATE
158 else:
159 visibility = PersonVisibility.PUBLIC
160 owner = self.factory.makePerson()
161 team = self.factory.makeTeam(
162 name='team', owner=owner, visibility=visibility,
163 membership_policy=TeamMembershipPolicy.RESTRICTED)
164 with person_logged_in(owner):
165 self.factory.makeMailingList(team, owner)
166 sender = self.factory.makePerson(email='me@eg.dom')
167 with person_logged_in(sender):
168 message = message_from_string(dedent("""\
169 From: me@eg.dom
170 To: team@lists.launchpad.test
171 Subject: A question
172 Message-ID: <first-post>
173 Date: Fri, 01 Aug 2000 01:08:59 -0000\n
174 I have a question about this team.
175 """))
176 return team, sender, message
177
178 def test_holdMessage(self):
179 # Calling holdMessages send a copy of the message text to Lp
180 # and notifies a team admins to moderate it.
181 team, sender, message = self.makeMailingListAndHeldMessage()
182 pop_notifications()
183 info = self.rpc_proxy.holdMessage('team', message.as_string())
184 notifications = pop_notifications()
185 found = getUtility(IMessageApprovalSet).getMessageByMessageID(
186 '<first-post>')
187 self.assertIs(True, info)
188 self.assertIsNot(None, found)
189 self.assertEqual(1, len(notifications))
190 self.assertEqual(
191 'New mailing list message requiring approval for Team',
192 notifications[0]['subject'])
193 self.assertTextMatchesExpressionIgnoreWhitespace(
194 '.*http://launchpad.test/~team/\+mailinglist-moderate.*',
195 notifications[0].get_payload())
196 self.assertEqual({}, self.rpc_proxy.getMessageDispositions())
197
198 def test_getMessageDispositions_accept(self):
199 # List moderators can approve messages.
200 team, sender, message = self.makeMailingListAndHeldMessage()
201 pop_notifications()
202 self.rpc_proxy.holdMessage('team', message.as_string())
203 found = getUtility(IMessageApprovalSet).getMessageByMessageID(
204 '<first-post>')
205 found.approve(team.teamowner)
206 self.assertEqual(PostedMessageStatus.APPROVAL_PENDING, found.status)
207 self.assertEqual(
208 {'<first-post>': ['team', 'accept']},
209 self.rpc_proxy.getMessageDispositions())
210 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__ = [
1010
11import re11import re
1212
13from six import ensure_text
13from six.moves import xmlrpc_client14from six.moves import xmlrpc_client
14from zope.component import getUtility15from zope.component import getUtility
15from zope.interface import implementer16from zope.interface import implementer
@@ -106,6 +107,7 @@ class MailingListAPIView(LaunchpadXMLRPCView):
106 """See `IMailingListAPIView`."""107 """See `IMailingListAPIView`."""
107 list_set = getUtility(IMailingListSet)108 list_set = getUtility(IMailingListSet)
108 for team_name, action_status in statuses.items():109 for team_name, action_status in statuses.items():
110 team_name = ensure_text(team_name)
109 mailing_list = list_set.get(team_name)111 mailing_list = list_set.get(team_name)
110 if mailing_list is None:112 if mailing_list is None:
111 return faults.NoSuchTeamMailingList(team_name)113 return faults.NoSuchTeamMailingList(team_name)
@@ -136,6 +138,7 @@ class MailingListAPIView(LaunchpadXMLRPCView):
136138
137 def getMembershipInformation(self, teams):139 def getMembershipInformation(self, teams):
138 """See `IMailingListAPIView`."""140 """See `IMailingListAPIView`."""
141 teams = [ensure_text(team) for team in teams]
139 mailing_list_set = getUtility(IMailingListSet)142 mailing_list_set = getUtility(IMailingListSet)
140 response = {}143 response = {}
141 # There are two sets of email addresses we need. The first is the set144 # There are two sets of email addresses we need. The first is the set
@@ -243,6 +246,7 @@ class MailingListAPIView(LaunchpadXMLRPCView):
243 # pass 8-bit strings.246 # pass 8-bit strings.
244 if isinstance(bytes, xmlrpc_client.Binary):247 if isinstance(bytes, xmlrpc_client.Binary):
245 bytes = bytes.data248 bytes = bytes.data
249 team_name = ensure_text(team_name)
246 # Although it is illegal for an email header to have unencoded250 # Although it is illegal for an email header to have unencoded
247 # non-ascii characters, it is better to let the list owner251 # non-ascii characters, it is better to let the list owner
248 # process the message than to cause an oops.252 # process the message than to cause an oops.

Subscribers

People subscribed via source and target branches

to status/vote changes: