Merge lp:~barry/launchpad/435604-mailman into lp:launchpad
- 435604-mailman
- Merge into devel
Proposed by
Barry Warsaw
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Brad Crittenden | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | not available | ||||
Proposed branch: | lp:~barry/launchpad/435604-mailman | ||||
Merge into: | lp:launchpad | ||||
Diff against target: |
824 lines 17 files modified
lib/canonical/launchpad/mailman/monkeypatches/__init__.py (+35/-80) lib/canonical/launchpad/mailman/monkeypatches/mm_cfg.py.in (+65/-0) lib/lp/services/mailman/doc/basic-integration.txt (+89/-0) lib/lp/services/mailman/doc/bounces.txt (+1/-0) lib/lp/services/mailman/doc/contact-address.txt (+2/-2) lib/lp/services/mailman/doc/create-lists.txt (+2/-2) lib/lp/services/mailman/doc/decorations.txt (+1/-2) lib/lp/services/mailman/doc/logging.txt (+27/-24) lib/lp/services/mailman/doc/messages.txt (+3/-1) lib/lp/services/mailman/doc/modify-lists.txt (+5/-3) lib/lp/services/mailman/doc/postings.txt (+17/-16) lib/lp/services/mailman/doc/reactivate-lists.txt (+4/-2) lib/lp/services/mailman/doc/recovery.txt (+9/-5) lib/lp/services/mailman/doc/staging.txt (+2/-3) lib/lp/services/mailman/doc/subscriptions.txt (+11/-7) lib/lp/services/mailman/testing/helpers.py (+1/-1) lib/lp/services/mailman/testing/logwatcher.py (+2/-2) |
||||
To merge this branch: | bzr merge lp:~barry/launchpad/435604-mailman | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Brad Crittenden (community) | release-critical | Approve | |
Paul Hummer (community) | Approve | ||
Review via email: mp+12380@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Barry Warsaw (barry) wrote : | # |
Revision history for this message
Paul Hummer (rockstar) : | # |
review:
Approve
Revision history for this message
Brad Crittenden (bac) wrote : | # |
Hi Barry,
Thanks for the fix. Not to beat a dead horse, but in the future try to keep RC candidate branches as tiny as possible.
Thanks also for hanging around last night as the release happened to ensure everything worked.
review:
Approve
(release-critical)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/canonical/launchpad/mailman/monkeypatches/__init__.py' | |||
2 | --- lib/canonical/launchpad/mailman/monkeypatches/__init__.py 2009-07-17 00:26:05 +0000 | |||
3 | +++ lib/canonical/launchpad/mailman/monkeypatches/__init__.py 2009-09-24 20:25:22 +0000 | |||
4 | @@ -38,7 +38,8 @@ | |||
5 | 38 | # will get appended to Mailman's sys.path. | 38 | # will get appended to Mailman's sys.path. |
6 | 39 | import canonical | 39 | import canonical |
7 | 40 | from canonical.launchpad.mailman.config import configure_siteowner | 40 | from canonical.launchpad.mailman.config import configure_siteowner |
9 | 41 | launchpad_top = os.path.dirname(os.path.dirname(canonical.__file__)) | 41 | launchpad_top = os.path.dirname( |
10 | 42 | os.path.dirname(os.path.dirname(canonical.__file__))) | ||
11 | 42 | # Read the email footer template for all Launchpad messages. | 43 | # Read the email footer template for all Launchpad messages. |
12 | 43 | from canonical.launchpad.helpers import get_email_template | 44 | from canonical.launchpad.helpers import get_email_template |
13 | 44 | footer = get_email_template('mailinglist-footer.txt') | 45 | footer = get_email_template('mailinglist-footer.txt') |
14 | @@ -46,85 +47,39 @@ | |||
15 | 46 | host, port = as_host_port(config.mailman.smtp) | 47 | host, port = as_host_port(config.mailman.smtp) |
16 | 47 | owner_address, owner_password = configure_siteowner( | 48 | owner_address, owner_password = configure_siteowner( |
17 | 48 | config.mailman.build_site_list_owner) | 49 | config.mailman.build_site_list_owner) |
97 | 49 | config_path = os.path.join(mailman_path, 'Mailman', 'mm_cfg.py') | 50 | config_path_in = os.path.join(os.path.dirname(__file__), 'mm_cfg.py.in') |
98 | 50 | config_file = open(config_path, 'w') | 51 | config_file_in = open(config_path_in) |
99 | 51 | try: | 52 | try: |
100 | 52 | print >> config_file, """\ | 53 | config_template = config_file_in.read() |
101 | 53 | # Automatically generated by runlaunchpad.py | 54 | finally: |
102 | 54 | 55 | config_file_in.close() | |
103 | 55 | # Set up Mailman's sys.path to pick up the top of Launchpad's tree | 56 | config_path_out = os.path.join(mailman_path, 'Mailman', 'mm_cfg.py') |
104 | 56 | import sys | 57 | config_file_out = open(config_path_out, 'w') |
105 | 57 | sys.path.insert(0, '%(launchpad_top)s') | 58 | try: |
106 | 58 | 59 | print >> config_file_out, config_template % dict( | |
107 | 59 | # Pick up Launchpad static overrides. This will also pick up the standard | 60 | launchpad_top=launchpad_top, |
108 | 60 | # Mailman.Defaults.* variables. | 61 | smtp_host=host, |
109 | 61 | from canonical.launchpad.mailman.monkeypatches.defaults import * | 62 | smtp_port=port, |
110 | 62 | 63 | xmlrpc_url=config.mailman.xmlrpc_url, | |
111 | 63 | # Our dynamic overrides of all the static defaults. | 64 | xmlrpc_sleeptime=config.mailman.xmlrpc_runner_sleep, |
112 | 64 | SMTPHOST = '%(smtp_host)s' | 65 | xmlrpc_subscription_batch_size |
113 | 65 | SMTPPORT = %(smtp_port)d | 66 | =config.mailman.subscription_batch_size, |
114 | 66 | 67 | site_list_owner=owner_address, | |
115 | 67 | # Configuration options for the XMLRPCRunner. | 68 | list_help_header=config.mailman.list_help_header, |
116 | 68 | XMLRPC_URL = '%(xmlrpc_url)s' | 69 | list_subscription_headers |
117 | 69 | XMLRPC_SLEEPTIME = %(xmlrpc_sleeptime)s | 70 | =config.mailman.list_subscription_headers, |
118 | 70 | XMLRPC_SUBSCRIPTION_BATCH_SIZE = %(xmlrpc_subscription_batch_size)s | 71 | archive_url_template=config.mailman.archive_url_template, |
119 | 71 | LAUNCHPAD_SHARED_SECRET = '%(shared_secret)s' | 72 | list_owner_header_template |
120 | 72 | 73 | =config.mailman.list_owner_header_template, | |
121 | 73 | # RFC 2369 header information. | 74 | footer=footer, |
122 | 74 | LIST_HELP_HEADER = '%(list_help_header)s' | 75 | var_dir=config.mailman.build_var_dir, |
123 | 75 | LIST_SUBSCRIPTION_HEADERS = '%(list_subscription_headers)s' | 76 | shared_secret=config.mailman.shared_secret, |
124 | 76 | LIST_ARCHIVE_HEADER_TEMPLATE = '%(archive_url_template)s' | 77 | soft_max_size=config.mailman.soft_max_size, |
125 | 77 | LIST_OWNER_HEADER_TEMPLATE = '%(list_owner_header_template)s' | 78 | hard_max_size=config.mailman.hard_max_size, |
126 | 78 | 79 | register_bounces_every=config.mailman.register_bounces_every, | |
127 | 79 | # Soft and hard maximum message size limits. Anything below the soft limit is | 80 | ) |
128 | 80 | # allowed directly through. Between the soft and hard limits, the message is | 81 | finally: |
129 | 81 | # held for approval. Above the hard limit, the message is logged and | 82 | config_file_out.close() |
51 | 82 | # discarded. Note that the normal Mailman size thresholds are ignored. | ||
52 | 83 | LAUNCHPAD_SOFT_MAX_SIZE = %(soft_max_size)d | ||
53 | 84 | LAUNCHPAD_HARD_MAX_SIZE = %(hard_max_size)d | ||
54 | 85 | |||
55 | 86 | SITE_LIST_OWNER = '%(site_list_owner)s' | ||
56 | 87 | |||
57 | 88 | DEFAULT_MSG_FOOTER = '''_______________________________________________ | ||
58 | 89 | %(footer)s''' | ||
59 | 90 | |||
60 | 91 | # Set up MHonArc archiving. | ||
61 | 92 | PUBLIC_EXTERNAL_ARCHIVER = '/usr/bin/mhonarc \ | ||
62 | 93 | -add \ | ||
63 | 94 | -dbfile %(var_dir)s/archives/private/%%(listname)s.mbox/mhonarc.db \ | ||
64 | 95 | -outdir %(var_dir)s/mhonarc/%%(listname)s \ | ||
65 | 96 | -definevar ML-NAME=%%(listname)s \ | ||
66 | 97 | -rcfile %(var_dir)s/data/lp-mhonarc-common.mrc \ | ||
67 | 98 | -stderr %(var_dir)s/logs/mhonarc \ | ||
68 | 99 | -stdout %(var_dir)s/logs/mhonarc \ | ||
69 | 100 | -spammode \ | ||
70 | 101 | -umask 022' | ||
71 | 102 | PRIVATE_EXTERNAL_ARCHIVER = PUBLIC_EXTERNAL_ARCHIVER | ||
72 | 103 | |||
73 | 104 | # How often do we run the bounce processor? For production, the default 15 | ||
74 | 105 | # minutes is fine, for testing we want to run it more often. | ||
75 | 106 | REGISTER_BOUNCES_EVERY = %(register_bounces_every)d | ||
76 | 107 | """ % dict( | ||
77 | 108 | launchpad_top=launchpad_top, | ||
78 | 109 | smtp_host=host, | ||
79 | 110 | smtp_port=port, | ||
80 | 111 | xmlrpc_url=config.mailman.xmlrpc_url, | ||
81 | 112 | xmlrpc_sleeptime=config.mailman.xmlrpc_runner_sleep, | ||
82 | 113 | xmlrpc_subscription_batch_size=config.mailman.subscription_batch_size, | ||
83 | 114 | site_list_owner=owner_address, | ||
84 | 115 | list_help_header=config.mailman.list_help_header, | ||
85 | 116 | list_subscription_headers=config.mailman.list_subscription_headers, | ||
86 | 117 | archive_url_template=config.mailman.archive_url_template, | ||
87 | 118 | list_owner_header_template=config.mailman.list_owner_header_template, | ||
88 | 119 | footer=footer, | ||
89 | 120 | var_dir=config.mailman.build_var_dir, | ||
90 | 121 | shared_secret=config.mailman.shared_secret, | ||
91 | 122 | soft_max_size=config.mailman.soft_max_size, | ||
92 | 123 | hard_max_size=config.mailman.hard_max_size, | ||
93 | 124 | register_bounces_every=config.mailman.register_bounces_every, | ||
94 | 125 | ) | ||
95 | 126 | finally: | ||
96 | 127 | config_file.close() | ||
130 | 128 | # Mailman's qrunner system requires runner modules to live in the | 83 | # Mailman's qrunner system requires runner modules to live in the |
131 | 129 | # Mailman.Queue package. Set things up so that there's a hook module in | 84 | # Mailman.Queue package. Set things up so that there's a hook module in |
132 | 130 | # there for the XMLRPCRunner. | 85 | # there for the XMLRPCRunner. |
133 | 131 | 86 | ||
134 | === added file 'lib/canonical/launchpad/mailman/monkeypatches/mm_cfg.py.in' | |||
135 | --- lib/canonical/launchpad/mailman/monkeypatches/mm_cfg.py.in 1970-01-01 00:00:00 +0000 | |||
136 | +++ lib/canonical/launchpad/mailman/monkeypatches/mm_cfg.py.in 2009-09-24 20:25:22 +0000 | |||
137 | @@ -0,0 +1,65 @@ | |||
138 | 1 | # Automatically generated by runlaunchpad.py | ||
139 | 2 | |||
140 | 3 | # Initialize sys.path so that the Mailman processes, which use the standard | ||
141 | 4 | # system Python instead of buildout's bin/py, can find all the necessary | ||
142 | 5 | # packages and modules. Some of these are in sourcecode and some are in | ||
143 | 6 | # buildout eggs. | ||
144 | 7 | # | ||
145 | 8 | # This is a two-step process. First, we hack sys.path in order to find a | ||
146 | 9 | # directory containing _pythonpath. Then the _pythonpath module does all the | ||
147 | 10 | # subsequent sys.path hacking necessary. | ||
148 | 11 | |||
149 | 12 | # Set up Mailman's sys.path to pick up the top of Launchpad's tree. This only | ||
150 | 13 | # gets us a sys.path | ||
151 | 14 | import sys | ||
152 | 15 | sys.path.insert(0, '%(launchpad_top)s') | ||
153 | 16 | import _pythonpath | ||
154 | 17 | |||
155 | 18 | # Pick up Launchpad static overrides. This will also pick up the standard | ||
156 | 19 | # Mailman.Defaults.* variables. | ||
157 | 20 | from canonical.launchpad.mailman.monkeypatches.defaults import * | ||
158 | 21 | |||
159 | 22 | # Our dynamic overrides of all the static defaults. | ||
160 | 23 | SMTPHOST = '%(smtp_host)s' | ||
161 | 24 | SMTPPORT = %(smtp_port)d | ||
162 | 25 | |||
163 | 26 | # Configuration options for the XMLRPCRunner. | ||
164 | 27 | XMLRPC_URL = '%(xmlrpc_url)s' | ||
165 | 28 | XMLRPC_SLEEPTIME = %(xmlrpc_sleeptime)s | ||
166 | 29 | XMLRPC_SUBSCRIPTION_BATCH_SIZE = %(xmlrpc_subscription_batch_size)s | ||
167 | 30 | LAUNCHPAD_SHARED_SECRET = '%(shared_secret)s' | ||
168 | 31 | |||
169 | 32 | # RFC 2369 header information. | ||
170 | 33 | LIST_HELP_HEADER = '%(list_help_header)s' | ||
171 | 34 | LIST_SUBSCRIPTION_HEADERS = '%(list_subscription_headers)s' | ||
172 | 35 | LIST_ARCHIVE_HEADER_TEMPLATE = '%(archive_url_template)s' | ||
173 | 36 | LIST_OWNER_HEADER_TEMPLATE = '%(list_owner_header_template)s' | ||
174 | 37 | |||
175 | 38 | # Soft and hard maximum message size limits. Anything below the soft limit is | ||
176 | 39 | # allowed directly through. Between the soft and hard limits, the message is | ||
177 | 40 | # held for approval. Above the hard limit, the message is logged and | ||
178 | 41 | # discarded. Note that the normal Mailman size thresholds are ignored. | ||
179 | 42 | LAUNCHPAD_SOFT_MAX_SIZE = %(soft_max_size)d | ||
180 | 43 | LAUNCHPAD_HARD_MAX_SIZE = %(hard_max_size)d | ||
181 | 44 | |||
182 | 45 | SITE_LIST_OWNER = '%(site_list_owner)s' | ||
183 | 46 | |||
184 | 47 | DEFAULT_MSG_FOOTER = '''_______________________________________________ | ||
185 | 48 | %(footer)s''' | ||
186 | 49 | |||
187 | 50 | # Set up MHonArc archiving. | ||
188 | 51 | PUBLIC_EXTERNAL_ARCHIVER = '/usr/bin/mhonarc \ | ||
189 | 52 | -add \ | ||
190 | 53 | -dbfile %(var_dir)s/archives/private/%%(listname)s.mbox/mhonarc.db \ | ||
191 | 54 | -outdir %(var_dir)s/mhonarc/%%(listname)s \ | ||
192 | 55 | -definevar ML-NAME=%%(listname)s \ | ||
193 | 56 | -rcfile %(var_dir)s/data/lp-mhonarc-common.mrc \ | ||
194 | 57 | -stderr %(var_dir)s/logs/mhonarc \ | ||
195 | 58 | -stdout %(var_dir)s/logs/mhonarc \ | ||
196 | 59 | -spammode \ | ||
197 | 60 | -umask 022' | ||
198 | 61 | PRIVATE_EXTERNAL_ARCHIVER = PUBLIC_EXTERNAL_ARCHIVER | ||
199 | 62 | |||
200 | 63 | # How often do we run the bounce processor? For production, the default 15 | ||
201 | 64 | # minutes is fine, for testing we want to run it more often. | ||
202 | 65 | REGISTER_BOUNCES_EVERY = %(register_bounces_every)d | ||
203 | 0 | 66 | ||
204 | === modified file 'lib/lp/services/mailman/doc/basic-integration.txt' | |||
205 | --- lib/lp/services/mailman/doc/basic-integration.txt 2009-06-23 17:51:24 +0000 | |||
206 | +++ lib/lp/services/mailman/doc/basic-integration.txt 2009-09-24 20:25:22 +0000 | |||
207 | @@ -29,3 +29,92 @@ | |||
208 | 29 | 29 | ||
209 | 30 | >>> withlist('withlist_2.can_import', '-q') | 30 | >>> withlist('withlist_2.can_import', '-q') |
210 | 31 | 99 | 31 | 99 |
211 | 32 | |||
212 | 33 | |||
213 | 34 | Binaries | ||
214 | 35 | ======== | ||
215 | 36 | |||
216 | 37 | Mailman contains a number of binary wrappers for integration between the MTA | ||
217 | 38 | and Mailman. Mailman's 'post' command accepts standard input from the MTA and | ||
218 | 39 | drops the resulting message in Mailman's incoming queue. | ||
219 | 40 | |||
220 | 41 | # See `subscriptions.txt`_ for more details. | ||
221 | 42 | >>> from lp.services.mailman.testing import helpers | ||
222 | 43 | >>> alpha = helpers.create_list('alpha') | ||
223 | 44 | >>> helpers.subscribe('Anne', 'alpha') | ||
224 | 45 | |||
225 | 46 | # Ignore the list creation notification message. | ||
226 | 47 | >>> smtpd.reset() | ||
227 | 48 | |||
228 | 49 | >>> sample_message = """\ | ||
229 | 50 | ... From: anne.person@example.com | ||
230 | 51 | ... To: alpha@lists.launchpad.dev | ||
231 | 52 | ... Subject: A test message | ||
232 | 53 | ... Message-ID: <aardvark> | ||
233 | 54 | ... | ||
234 | 55 | ... This is a test message. | ||
235 | 56 | ... """ | ||
236 | 57 | |||
237 | 58 | # The path to the binary we're testing is relative to the top of the | ||
238 | 59 | # Launchpad source tree. | ||
239 | 60 | >>> import canonical | ||
240 | 61 | >>> launchpad_top = os.path.dirname( | ||
241 | 62 | ... os.path.dirname(os.path.dirname(canonical.__file__))) | ||
242 | 63 | >>> binary = os.path.join(launchpad_top, | ||
243 | 64 | ... 'lib/mailman/mail/mailman') | ||
244 | 65 | |||
245 | 66 | >>> mailman = subprocess.Popen( | ||
246 | 67 | ... (binary, 'post', 'alpha'), | ||
247 | 68 | ... stdin=subprocess.PIPE, | ||
248 | 69 | ... stdout=subprocess.PIPE, | ||
249 | 70 | ... stderr=subprocess.PIPE) | ||
250 | 71 | |||
251 | 72 | >>> stdout, stderr = mailman.communicate(sample_message) | ||
252 | 73 | >>> mailman.returncode | ||
253 | 74 | 0 | ||
254 | 75 | >>> print stdout | ||
255 | 76 | <BLANKLINE> | ||
256 | 77 | >>> print stderr | ||
257 | 78 | <BLANKLINE> | ||
258 | 79 | |||
259 | 80 | The message was delivered to Anne and the archiver. | ||
260 | 81 | |||
261 | 82 | >>> smtpd_watcher.wait_for_mbox_delivery('aardvark') | ||
262 | 83 | >>> messages = list(smtpd) | ||
263 | 84 | >>> len(messages) | ||
264 | 85 | 2 | ||
265 | 86 | |||
266 | 87 | >>> for message in messages: | ||
267 | 88 | ... if message['x-rcptto'] == 'anne.person@example.com': | ||
268 | 89 | ... break | ||
269 | 90 | |||
270 | 91 | >>> print message.as_string() | ||
271 | 92 | From: anne.person@example.com | ||
272 | 93 | To: alpha@lists.launchpad.dev | ||
273 | 94 | Message-ID: <aardvark> | ||
274 | 95 | Subject: [Alpha] A test message | ||
275 | 96 | X-BeenThere: alpha@lists.launchpad.dev | ||
276 | 97 | X-Mailman-Version: ... | ||
277 | 98 | Precedence: list | ||
278 | 99 | List-Id: <alpha.lists.launchpad.dev> | ||
279 | 100 | List-Help: <http://help.launchpad.dev/ListHelp> | ||
280 | 101 | List-Subscribe: <http://launchpad.dev/~alpha> | ||
281 | 102 | List-Unsubscribe: <http://launchpad.dev/~alpha> | ||
282 | 103 | List-Post: <mailto:alpha@lists.launchpad.dev> | ||
283 | 104 | List-Archive: <http://lists.launchpad.dev/alpha> | ||
284 | 105 | List-Owner: <http://launchpad.dev/~alpha> | ||
285 | 106 | MIME-Version: 1.0 | ||
286 | 107 | Content-Type: text/plain; charset="us-ascii" | ||
287 | 108 | Content-Transfer-Encoding: 7bit | ||
288 | 109 | Sender: alpha-bounces+anne.person=example.com@lists.launchpad.dev | ||
289 | 110 | Errors-To: alpha-bounces+anne.person=example.com@lists.launchpad.dev | ||
290 | 111 | X-Peer: ... | ||
291 | 112 | X-MailFrom: alpha-bounces+anne.person=example.com@lists.launchpad.dev | ||
292 | 113 | X-RcptTo: anne.person@example.com | ||
293 | 114 | <BLANKLINE> | ||
294 | 115 | This is a test message. | ||
295 | 116 | _______________________________________________ | ||
296 | 117 | Mailing list: http://launchpad.dev/~alpha | ||
297 | 118 | Post to : alpha@lists.launchpad.dev | ||
298 | 119 | Unsubscribe : http://launchpad.dev/~alpha | ||
299 | 120 | More help : http://help.launchpad.dev/ListHelp | ||
300 | 32 | 121 | ||
301 | === modified file 'lib/lp/services/mailman/doc/bounces.txt' | |||
302 | --- lib/lp/services/mailman/doc/bounces.txt 2009-06-03 16:03:04 +0000 | |||
303 | +++ lib/lp/services/mailman/doc/bounces.txt 2009-09-24 20:25:22 +0000 | |||
304 | @@ -1,3 +1,4 @@ | |||
305 | 1 | ================= | ||
306 | 1 | Bounce processing | 2 | Bounce processing |
307 | 2 | ================= | 3 | ================= |
308 | 3 | 4 | ||
309 | 4 | 5 | ||
310 | === modified file 'lib/lp/services/mailman/doc/contact-address.txt' | |||
311 | --- lib/lp/services/mailman/doc/contact-address.txt 2009-06-26 21:58:35 +0000 | |||
312 | +++ lib/lp/services/mailman/doc/contact-address.txt 2009-09-24 20:25:22 +0000 | |||
313 | @@ -28,7 +28,7 @@ | |||
314 | 28 | >>> browser.getControl('Change').click() | 28 | >>> browser.getControl('Change').click() |
315 | 29 | 29 | ||
316 | 30 | >>> browser.getLink('Change details').click() | 30 | >>> browser.getLink('Change details').click() |
318 | 31 | >>> browser.getLink('Change contact address').click() | 31 | >>> browser.getLink('Set contact address').click() |
319 | 32 | >>> control = browser.getControl(name='field.contact_method') | 32 | >>> control = browser.getControl(name='field.contact_method') |
320 | 33 | >>> [strip_label(label) for label in control.displayValue] | 33 | >>> [strip_label(label) for label in control.displayValue] |
321 | 34 | ['The Launchpad mailing list for this team...] | 34 | ['The Launchpad mailing list for this team...] |
322 | @@ -237,7 +237,7 @@ | |||
323 | 237 | >>> browser.getControl('Change').click() | 237 | >>> browser.getControl('Change').click() |
324 | 238 | 238 | ||
325 | 239 | >>> browser.getLink('Change details').click() | 239 | >>> browser.getLink('Change details').click() |
327 | 240 | >>> browser.getLink('Change contact address').click() | 240 | >>> browser.getLink('Set contact address').click() |
328 | 241 | >>> control = browser.getControl(name='field.contact_method') | 241 | >>> control = browser.getControl(name='field.contact_method') |
329 | 242 | >>> [strip_label(label) for label in control.displayValue] | 242 | >>> [strip_label(label) for label in control.displayValue] |
330 | 243 | ['Each member individually'] | 243 | ['Each member individually'] |
331 | 244 | 244 | ||
332 | === modified file 'lib/lp/services/mailman/doc/create-lists.txt' | |||
333 | --- lib/lp/services/mailman/doc/create-lists.txt 2009-06-23 17:51:24 +0000 | |||
334 | +++ lib/lp/services/mailman/doc/create-lists.txt 2009-09-24 20:25:22 +0000 | |||
335 | @@ -21,7 +21,7 @@ | |||
336 | 21 | To request a mailing list, No Privileges Person navigates to the 'Configure | 21 | To request a mailing list, No Privileges Person navigates to the 'Configure |
337 | 22 | mailing list' page and registers their application for a mailing list. | 22 | mailing list' page and registers their application for a mailing list. |
338 | 23 | 23 | ||
340 | 24 | >>> browser.getLink('Configure mailing list').click() | 24 | >>> browser.getLink('Create a mailing list').click() |
341 | 25 | >>> browser.getControl('Apply for Mailing List').click() | 25 | >>> browser.getControl('Apply for Mailing List').click() |
342 | 26 | 26 | ||
343 | 27 | At this point, Mailman has still not created the mailing list. | 27 | At this point, Mailman has still not created the mailing list. |
344 | @@ -56,7 +56,7 @@ | |||
345 | 56 | >>> browser.getControl(name='field.subscriptionpolicy').displayValue = [ | 56 | >>> browser.getControl(name='field.subscriptionpolicy').displayValue = [ |
346 | 57 | ... 'Open Team'] | 57 | ... 'Open Team'] |
347 | 58 | >>> browser.getControl('Create').click() | 58 | >>> browser.getControl('Create').click() |
349 | 59 | >>> browser.getLink('Configure mailing list').click() | 59 | >>> browser.getLink('Create a mailing list').click() |
350 | 60 | >>> browser.getControl('Apply for Mailing List').click() | 60 | >>> browser.getControl('Apply for Mailing List').click() |
351 | 61 | 61 | ||
352 | 62 | This time, however, the mailing list expert declines the application for a new | 62 | This time, however, the mailing list expert declines the application for a new |
353 | 63 | 63 | ||
354 | === modified file 'lib/lp/services/mailman/doc/decorations.txt' | |||
355 | --- lib/lp/services/mailman/doc/decorations.txt 2009-06-23 19:33:57 +0000 | |||
356 | +++ lib/lp/services/mailman/doc/decorations.txt 2009-09-24 20:25:22 +0000 | |||
357 | @@ -117,8 +117,7 @@ | |||
358 | 117 | >>> browser = Browser('no-priv@canonical.com:test') | 117 | >>> browser = Browser('no-priv@canonical.com:test') |
359 | 118 | >>> browser.open('http://launchpad.dev:8085/~itest-one') | 118 | >>> browser.open('http://launchpad.dev:8085/~itest-one') |
360 | 119 | >>> browser.getLink(id='mailing-list-archive') | 119 | >>> browser.getLink(id='mailing-list-archive') |
363 | 120 | <Link text='Mailing list archive' | 120 | <Link text='View archive' url='http://lists.launchpad.dev/itest-one'> |
362 | 121 | url='http://lists.launchpad.dev/itest-one'> | ||
364 | 122 | >>> print message['list-archive'] | 121 | >>> print message['list-archive'] |
365 | 123 | <http://lists.launchpad.dev/itest-one> | 122 | <http://lists.launchpad.dev/itest-one> |
366 | 124 | 123 | ||
367 | 125 | 124 | ||
368 | === modified file 'lib/lp/services/mailman/doc/logging.txt' | |||
369 | --- lib/lp/services/mailman/doc/logging.txt 2009-04-17 10:32:16 +0000 | |||
370 | +++ lib/lp/services/mailman/doc/logging.txt 2009-09-24 20:25:22 +0000 | |||
371 | @@ -1,9 +1,12 @@ | |||
373 | 1 | = Logging and OOPS reporting = | 1 | ========================== |
374 | 2 | Logging and OOPS reporting | ||
375 | 3 | ========================== | ||
376 | 2 | 4 | ||
377 | 3 | The Mailman XMLRPCRunner logs errors and reports OOPSes. | 5 | The Mailman XMLRPCRunner logs errors and reports OOPSes. |
378 | 4 | 6 | ||
379 | 5 | 7 | ||
381 | 6 | = MailmanErrorUtility = | 8 | MailmanErrorUtility |
382 | 9 | =================== | ||
383 | 7 | 10 | ||
384 | 8 | The MailmanErrorUtility is a ErrorReportingUtility that is configured | 11 | The MailmanErrorUtility is a ErrorReportingUtility that is configured |
385 | 9 | in the [mailman] section of config. | 12 | in the [mailman] section of config. |
386 | @@ -13,21 +16,22 @@ | |||
387 | 13 | ... MailmanErrorUtility) | 16 | ... MailmanErrorUtility) |
388 | 14 | 17 | ||
389 | 15 | >>> error_utility = MailmanErrorUtility() | 18 | >>> error_utility = MailmanErrorUtility() |
405 | 16 | >>> error_utility._default_config_section | 19 | >>> print error_utility._default_config_section |
406 | 17 | 'mailman' | 20 | mailman |
407 | 18 | 21 | ||
408 | 19 | >>> error_utility.prefix | 22 | >>> print error_utility.prefix |
409 | 20 | 'TMMX' | 23 | TMMX |
410 | 21 | >>> config.mailman.oops_prefix | 24 | >>> print config.mailman.oops_prefix |
411 | 22 | 'TMMX' | 25 | TMMX |
412 | 23 | 26 | ||
413 | 24 | >>> error_utility.error_dir | 27 | >>> print error_utility.error_dir |
414 | 25 | '/var/tmp/mailman-xmlrpc.test' | 28 | /var/tmp/mailman-xmlrpc.test |
415 | 26 | >>> config.mailman.error_dir | 29 | >>> print config.mailman.error_dir |
416 | 27 | '/var/tmp/mailman-xmlrpc.test' | 30 | /var/tmp/mailman-xmlrpc.test |
417 | 28 | 31 | ||
418 | 29 | 32 | ||
419 | 30 | = Error logging = | 33 | Error logging |
420 | 34 | ============= | ||
421 | 31 | 35 | ||
422 | 32 | The log_exception() function is used by XMLRPCRunner to report known | 36 | The log_exception() function is used by XMLRPCRunner to report known |
423 | 33 | exceptions. It reports the OOPS. | 37 | exceptions. It reports the OOPS. |
424 | @@ -44,12 +48,12 @@ | |||
425 | 44 | 48 | ||
426 | 45 | >>> test_log_exception() | 49 | >>> test_log_exception() |
427 | 46 | >>> oops = error_utility.getLastOopsReport() | 50 | >>> oops = error_utility.getLastOopsReport() |
434 | 47 | >>> oops.id | 51 | >>> print oops.id |
435 | 48 | 'OOPS-...TMMX...' | 52 | OOPS-...TMMX... |
436 | 49 | >>> oops.type | 53 | >>> print oops.type |
437 | 50 | 'AssertionError' | 54 | AssertionError |
438 | 51 | >>> oops.value | 55 | >>> print oops.value |
439 | 52 | 'There is an OOPS in progress.' | 56 | There is an OOPS in progress. |
440 | 53 | >>> print oops.tb_text | 57 | >>> print oops.tb_text |
441 | 54 | Traceback (most recent call last): | 58 | Traceback (most recent call last): |
442 | 55 | ... | 59 | ... |
443 | @@ -77,4 +81,3 @@ | |||
444 | 77 | the _create() method. The create-lists-txt test was run to generate a | 81 | the _create() method. The create-lists-txt test was run to generate a |
445 | 78 | "NameError: global name 'defect' is not defined". The error was written | 82 | "NameError: global name 'defect' is not defined". The error was written |
446 | 79 | to the xmlrpc log, and an OOPS was reported. | 83 | to the xmlrpc log, and an OOPS was reported. |
447 | 80 | |||
448 | 81 | 84 | ||
449 | === modified file 'lib/lp/services/mailman/doc/messages.txt' | |||
450 | --- lib/lp/services/mailman/doc/messages.txt 2009-04-17 10:32:16 +0000 | |||
451 | +++ lib/lp/services/mailman/doc/messages.txt 2009-09-24 20:25:22 +0000 | |||
452 | @@ -1,4 +1,6 @@ | |||
454 | 1 | = Messages = | 1 | ======== |
455 | 2 | Messages | ||
456 | 3 | ======== | ||
457 | 2 | 4 | ||
458 | 3 | Launchpad uses a custom set of message templates that it installs | 5 | Launchpad uses a custom set of message templates that it installs |
459 | 4 | in mailman/templates/site. The installation conforms to the standard | 6 | in mailman/templates/site. The installation conforms to the standard |
460 | 5 | 7 | ||
461 | === modified file 'lib/lp/services/mailman/doc/modify-lists.txt' | |||
462 | --- lib/lp/services/mailman/doc/modify-lists.txt 2009-06-03 16:03:04 +0000 | |||
463 | +++ lib/lp/services/mailman/doc/modify-lists.txt 2009-09-24 20:25:22 +0000 | |||
464 | @@ -1,4 +1,6 @@ | |||
466 | 1 | = Modifying lists = | 1 | =============== |
467 | 2 | Modifying lists | ||
468 | 3 | =============== | ||
469 | 2 | 4 | ||
470 | 3 | A team administrator can make changes to the mailing list, although currently | 5 | A team administrator can make changes to the mailing list, although currently |
471 | 4 | the only thing they can change is the list's welcome message. | 6 | the only thing they can change is the list's welcome message. |
472 | @@ -13,7 +15,7 @@ | |||
473 | 13 | >>> browser.getControl(name='field.subscriptionpolicy').displayValue = [ | 15 | >>> browser.getControl(name='field.subscriptionpolicy').displayValue = [ |
474 | 14 | ... 'Open Team'] | 16 | ... 'Open Team'] |
475 | 15 | >>> browser.getControl('Create').click() | 17 | >>> browser.getControl('Create').click() |
477 | 16 | >>> browser.getLink('Configure mailing list').click() | 18 | >>> browser.getLink('Create a mailing list').click() |
478 | 17 | >>> browser.getControl('Apply for Mailing List').click() | 19 | >>> browser.getControl('Apply for Mailing List').click() |
479 | 18 | 20 | ||
480 | 19 | Before approving the creation of the mailing list, let's set the welcome | 21 | Before approving the creation of the mailing list, let's set the welcome |
481 | @@ -26,7 +28,7 @@ | |||
482 | 26 | >>> from canonical.launchpad.interfaces import ( | 28 | >>> from canonical.launchpad.interfaces import ( |
483 | 27 | ... ILaunchpadCelebrities, IMailingListSet, MailingListStatus) | 29 | ... ILaunchpadCelebrities, IMailingListSet, MailingListStatus) |
484 | 28 | 30 | ||
486 | 29 | >>> login('foo.bar@canonical.com') | 31 | >>> login('admin@canonical.com') |
487 | 30 | >>> list_set = getUtility(IMailingListSet) | 32 | >>> list_set = getUtility(IMailingListSet) |
488 | 31 | >>> list_one = list_set.get('itest-one') | 33 | >>> list_one = list_set.get('itest-one') |
489 | 32 | >>> list_one.welcome_message = 'Greetings team members!' | 34 | >>> list_one.welcome_message = 'Greetings team members!' |
490 | 33 | 35 | ||
491 | === modified file 'lib/lp/services/mailman/doc/postings.txt' | |||
492 | --- lib/lp/services/mailman/doc/postings.txt 2009-06-26 21:42:20 +0000 | |||
493 | +++ lib/lp/services/mailman/doc/postings.txt 2009-09-24 20:25:22 +0000 | |||
494 | @@ -1,3 +1,4 @@ | |||
495 | 1 | ======= | ||
496 | 1 | Posting | 2 | Posting |
497 | 2 | ======= | 3 | ======= |
498 | 3 | 4 | ||
499 | @@ -14,7 +15,7 @@ | |||
500 | 14 | 15 | ||
501 | 15 | 16 | ||
502 | 16 | Non-member postings | 17 | Non-member postings |
504 | 17 | ------------------- | 18 | =================== |
505 | 18 | 19 | ||
506 | 19 | Postings from addresses that are not registered and verified with Launchpad | 20 | Postings from addresses that are not registered and verified with Launchpad |
507 | 20 | are summarily discarded. | 21 | are summarily discarded. |
508 | @@ -37,7 +38,7 @@ | |||
509 | 37 | 38 | ||
510 | 38 | 39 | ||
511 | 39 | Non-validated member postings | 40 | Non-validated member postings |
513 | 40 | ----------------------------- | 41 | ============================= |
514 | 41 | 42 | ||
515 | 42 | Similarly, an address that has been registered with Launchpad but not verified | 43 | Similarly, an address that has been registered with Launchpad but not verified |
516 | 43 | will also be summarily discarded. Anne registers with Launchpad but does not | 44 | will also be summarily discarded. Anne registers with Launchpad but does not |
517 | @@ -48,7 +49,7 @@ | |||
518 | 48 | >>> from canonical.launchpad.ftests import login, logout | 49 | >>> from canonical.launchpad.ftests import login, logout |
519 | 49 | >>> from canonical.launchpad.interfaces import EmailAddressStatus | 50 | >>> from canonical.launchpad.interfaces import EmailAddressStatus |
520 | 50 | 51 | ||
522 | 51 | >>> login('foo.bar@canonical.com') | 52 | >>> login('admin@canonical.com') |
523 | 52 | >>> anne = factory.makePersonByName('Anne') | 53 | >>> anne = factory.makePersonByName('Anne') |
524 | 53 | >>> alternative_email = get_alternative_email(anne) | 54 | >>> alternative_email = get_alternative_email(anne) |
525 | 54 | 55 | ||
526 | @@ -75,7 +76,7 @@ | |||
527 | 75 | 76 | ||
528 | 76 | 77 | ||
529 | 77 | Unsubscribed Launchpad members | 78 | Unsubscribed Launchpad members |
531 | 78 | ------------------------------ | 79 | ============================== |
532 | 79 | 80 | ||
533 | 80 | Anne's preferred email address is still validated, and she posts a message | 81 | Anne's preferred email address is still validated, and she posts a message |
534 | 81 | from that address. However, because she has not yet joined the team or | 82 | from that address. However, because she has not yet joined the team or |
535 | @@ -336,7 +337,7 @@ | |||
536 | 336 | 337 | ||
537 | 337 | 338 | ||
538 | 338 | Unsubscribed team member | 339 | Unsubscribed team member |
540 | 339 | ------------------------ | 340 | ======================== |
541 | 340 | 341 | ||
542 | 341 | Once Anne joins the team, she may post to it, though until she subscribes to | 342 | Once Anne joins the team, she may post to it, though until she subscribes to |
543 | 342 | the mailing list, she will not get a copy of the message. | 343 | the mailing list, she will not get a copy of the message. |
544 | @@ -356,7 +357,7 @@ | |||
545 | 356 | 357 | ||
546 | 357 | >>> from zope.component import getUtility | 358 | >>> from zope.component import getUtility |
547 | 358 | >>> from canonical.launchpad.interfaces import IPersonSet | 359 | >>> from canonical.launchpad.interfaces import IPersonSet |
549 | 359 | >>> login('foo.bar@canonical.com') | 360 | >>> login('admin@canonical.com') |
550 | 360 | >>> team_one = getUtility(IPersonSet).getByName('itest-one') | 361 | >>> team_one = getUtility(IPersonSet).getByName('itest-one') |
551 | 361 | >>> anne.join(team_one) | 362 | >>> anne.join(team_one) |
552 | 362 | >>> transaction.commit() | 363 | >>> transaction.commit() |
553 | @@ -407,7 +408,7 @@ | |||
554 | 407 | 408 | ||
555 | 408 | 409 | ||
556 | 409 | Verified and registered member postings | 410 | Verified and registered member postings |
558 | 410 | --------------------------------------- | 411 | ======================================= |
559 | 411 | 412 | ||
560 | 412 | Anne now subscribes to the team's mailing list. She gets a copy of each | 413 | Anne now subscribes to the team's mailing list. She gets a copy of each |
561 | 413 | message posted to the mailing list. | 414 | message posted to the mailing list. |
562 | @@ -503,7 +504,7 @@ | |||
563 | 503 | 504 | ||
564 | 504 | However, once she validates this address, she can post from it. | 505 | However, once she validates this address, she can post from it. |
565 | 505 | 506 | ||
567 | 506 | >>> login('foo.bar@canonical.com') | 507 | >>> login('admin@canonical.com') |
568 | 507 | >>> alternative_email.status = EmailAddressStatus.VALIDATED | 508 | >>> alternative_email.status = EmailAddressStatus.VALIDATED |
569 | 508 | >>> logout() | 509 | >>> logout() |
570 | 509 | >>> transaction.commit() | 510 | >>> transaction.commit() |
571 | @@ -570,11 +571,11 @@ | |||
572 | 570 | 571 | ||
573 | 571 | 572 | ||
574 | 572 | Leaving and re-joining the team | 573 | Leaving and re-joining the team |
576 | 573 | ------------------------------- | 574 | =============================== |
577 | 574 | 575 | ||
578 | 575 | Anne now leaves the team, but she does not unsubscribe from the mailing list. | 576 | Anne now leaves the team, but she does not unsubscribe from the mailing list. |
579 | 576 | 577 | ||
581 | 577 | >>> login('foo.bar@canonical.com') | 578 | >>> login('admin@canonical.com') |
582 | 578 | >>> team_one = getUtility(IPersonSet).getByName('itest-one') | 579 | >>> team_one = getUtility(IPersonSet).getByName('itest-one') |
583 | 579 | >>> anne.leave(team_one) | 580 | >>> anne.leave(team_one) |
584 | 580 | >>> logout() | 581 | >>> logout() |
585 | @@ -619,7 +620,7 @@ | |||
586 | 619 | Anne re-joins the team and once again can post to the mailing list. She does | 620 | Anne re-joins the team and once again can post to the mailing list. She does |
587 | 620 | not need to re-subscribe to the mailing list. | 621 | not need to re-subscribe to the mailing list. |
588 | 621 | 622 | ||
590 | 622 | >>> login('foo.bar@canonical.com') | 623 | >>> login('admin@canonical.com') |
591 | 623 | >>> anne.join(team_one) | 624 | >>> anne.join(team_one) |
592 | 624 | >>> logout() | 625 | >>> logout() |
593 | 625 | >>> transaction.commit() | 626 | >>> transaction.commit() |
594 | @@ -654,12 +655,12 @@ | |||
595 | 654 | 655 | ||
596 | 655 | 656 | ||
597 | 656 | First post moderation | 657 | First post moderation |
599 | 657 | --------------------- | 658 | ===================== |
600 | 658 | 659 | ||
601 | 659 | Normally, Launchpad members who are not subscribed to the mailing list will | 660 | Normally, Launchpad members who are not subscribed to the mailing list will |
602 | 660 | have their posts held for moderation. | 661 | have their posts held for moderation. |
603 | 661 | 662 | ||
605 | 662 | >>> login('foo.bar@canonical.com') | 663 | >>> login('admin@canonical.com') |
606 | 663 | >>> bart = factory.makePersonByName('Bart') | 664 | >>> bart = factory.makePersonByName('Bart') |
607 | 664 | >>> transaction.commit() | 665 | >>> transaction.commit() |
608 | 665 | >>> bart.personal_standing | 666 | >>> bart.personal_standing |
609 | @@ -694,7 +695,7 @@ | |||
610 | 694 | list. | 695 | list. |
611 | 695 | 696 | ||
612 | 696 | >>> from canonical.launchpad.interfaces import PersonalStanding | 697 | >>> from canonical.launchpad.interfaces import PersonalStanding |
614 | 697 | >>> login('foo.bar@canonical.com') | 698 | >>> login('admin@canonical.com') |
615 | 698 | >>> bart.personal_standing = PersonalStanding.GOOD | 699 | >>> bart.personal_standing = PersonalStanding.GOOD |
616 | 699 | >>> transaction.commit() | 700 | >>> transaction.commit() |
617 | 700 | 701 | ||
618 | @@ -809,7 +810,7 @@ | |||
619 | 809 | 810 | ||
620 | 810 | 811 | ||
621 | 811 | Preventing archiver forgeries | 812 | Preventing archiver forgeries |
623 | 812 | ----------------------------- | 813 | ============================= |
624 | 813 | 814 | ||
625 | 814 | We archive messages by sending them to a special address owned by the Mail | 815 | We archive messages by sending them to a special address owned by the Mail |
626 | 815 | Archive <http://www.mail-archive.com>. This address becomes a recipient of | 816 | Archive <http://www.mail-archive.com>. This address becomes a recipient of |
627 | @@ -834,7 +835,7 @@ | |||
628 | 834 | 835 | ||
629 | 835 | 836 | ||
630 | 836 | Large messages | 837 | Large messages |
632 | 837 | -------------- | 838 | ============== |
633 | 838 | 839 | ||
634 | 839 | Only messages which are less than about 40k in size are allowed straight | 840 | Only messages which are less than about 40k in size are allowed straight |
635 | 840 | through on the mailing list. A message bigger than that will be held for | 841 | through on the mailing list. A message bigger than that will be held for |
636 | 841 | 842 | ||
637 | === modified file 'lib/lp/services/mailman/doc/reactivate-lists.txt' | |||
638 | --- lib/lp/services/mailman/doc/reactivate-lists.txt 2009-05-06 15:13:39 +0000 | |||
639 | +++ lib/lp/services/mailman/doc/reactivate-lists.txt 2009-09-24 20:25:22 +0000 | |||
640 | @@ -1,4 +1,6 @@ | |||
642 | 1 | = Re-activating mailing lists = | 1 | =========================== |
643 | 2 | Re-activating mailing lists | ||
644 | 3 | =========================== | ||
645 | 2 | 4 | ||
646 | 3 | A team administrator may re-activate a previously deactivated mailing list | 5 | A team administrator may re-activate a previously deactivated mailing list |
647 | 4 | without the need for approval from a Launchpad administrator. When the | 6 | without the need for approval from a Launchpad administrator. When the |
648 | @@ -48,7 +50,7 @@ | |||
649 | 48 | 50 | ||
650 | 49 | Now the team owner reactivates the list. | 51 | Now the team owner reactivates the list. |
651 | 50 | 52 | ||
653 | 51 | >>> browser.getLink('Configure mailing list').click() | 53 | >>> browser.getLink('Create a mailing list').click() |
654 | 52 | >>> browser.getControl('Reactivate this Mailing List').click() | 54 | >>> browser.getControl('Reactivate this Mailing List').click() |
655 | 53 | >>> xmlrpc_watcher.wait_for_reactivation('itest-one') | 55 | >>> xmlrpc_watcher.wait_for_reactivation('itest-one') |
656 | 54 | 56 | ||
657 | 55 | 57 | ||
658 | === modified file 'lib/lp/services/mailman/doc/recovery.txt' | |||
659 | --- lib/lp/services/mailman/doc/recovery.txt 2009-06-03 16:03:04 +0000 | |||
660 | +++ lib/lp/services/mailman/doc/recovery.txt 2009-09-24 20:25:22 +0000 | |||
661 | @@ -1,4 +1,6 @@ | |||
663 | 1 | = Error recovery = | 1 | ============== |
664 | 2 | Error recovery | ||
665 | 3 | ============== | ||
666 | 2 | 4 | ||
667 | 3 | Under various conditions, reporting status from Mailman to Launchpad can | 5 | Under various conditions, reporting status from Mailman to Launchpad can |
668 | 4 | fail. For example, if during construction, the reportStatus() call has | 6 | fail. For example, if during construction, the reportStatus() call has |
669 | @@ -18,14 +20,15 @@ | |||
670 | 18 | >>> browser.getControl(name='field.subscriptionpolicy').displayValue = [ | 20 | >>> browser.getControl(name='field.subscriptionpolicy').displayValue = [ |
671 | 19 | ... 'Open Team'] | 21 | ... 'Open Team'] |
672 | 20 | >>> browser.getControl('Create').click() | 22 | >>> browser.getControl('Create').click() |
674 | 21 | >>> browser.getLink('Configure mailing list').click() | 23 | >>> browser.getLink('Create a mailing list').click() |
675 | 22 | >>> browser.getControl('Apply for Mailing List').click() | 24 | >>> browser.getControl('Apply for Mailing List').click() |
676 | 23 | 25 | ||
677 | 24 | >>> from lp.services.mailman.testing import helpers | 26 | >>> from lp.services.mailman.testing import helpers |
678 | 25 | >>> list_one = helpers.review_list('itest-one') | 27 | >>> list_one = helpers.review_list('itest-one') |
679 | 26 | 28 | ||
680 | 27 | 29 | ||
682 | 28 | == Lost construction == | 30 | Lost construction |
683 | 31 | ================= | ||
684 | 29 | 32 | ||
685 | 30 | The mailing list is now active, but let's say that the status reporting | 33 | The mailing list is now active, but let's say that the status reporting |
686 | 31 | failed. The mailing list would be in the CONSTRUCTING state. We | 34 | failed. The mailing list would be in the CONSTRUCTING state. We |
687 | @@ -37,7 +40,7 @@ | |||
688 | 37 | >>> from canonical.launchpad.interfaces import ( | 40 | >>> from canonical.launchpad.interfaces import ( |
689 | 38 | ... IMailingListSet, MailingListStatus) | 41 | ... IMailingListSet, MailingListStatus) |
690 | 39 | >>> from canonical.launchpad.ftests import login, logout | 42 | >>> from canonical.launchpad.ftests import login, logout |
692 | 40 | >>> login('foo.bar@canonical.com') | 43 | >>> login('admin@canonical.com') |
693 | 41 | >>> mailing_list_set = getUtility(IMailingListSet) | 44 | >>> mailing_list_set = getUtility(IMailingListSet) |
694 | 42 | >>> itest_one = removeSecurityProxy(mailing_list_set.get('itest-one')) | 45 | >>> itest_one = removeSecurityProxy(mailing_list_set.get('itest-one')) |
695 | 43 | >>> itest_one.status = MailingListStatus.CONSTRUCTING | 46 | >>> itest_one.status = MailingListStatus.CONSTRUCTING |
696 | @@ -84,7 +87,8 @@ | |||
697 | 84 | <DBItem MailingListStatus.ACTIVE, (5) Active> | 87 | <DBItem MailingListStatus.ACTIVE, (5) Active> |
698 | 85 | 88 | ||
699 | 86 | 89 | ||
701 | 87 | == Lost updates == | 90 | Lost updates |
702 | 91 | ============ | ||
703 | 88 | 92 | ||
704 | 89 | Another situation can occur if the team owner updates the mailing list, | 93 | Another situation can occur if the team owner updates the mailing list, |
705 | 90 | say by giving it a welcome message. | 94 | say by giving it a welcome message. |
706 | 91 | 95 | ||
707 | === modified file 'lib/lp/services/mailman/doc/staging.txt' | |||
708 | --- lib/lp/services/mailman/doc/staging.txt 2009-06-30 17:37:35 +0000 | |||
709 | +++ lib/lp/services/mailman/doc/staging.txt 2009-09-24 20:25:22 +0000 | |||
710 | @@ -20,8 +20,7 @@ | |||
711 | 20 | 20 | ||
712 | 21 | >>> from canonical.launchpad.ftests import login, logout | 21 | >>> from canonical.launchpad.ftests import login, logout |
713 | 22 | 22 | ||
716 | 23 | >>> login('foo.bar@canonical.com') | 23 | >>> login('admin@canonical.com') |
715 | 24 | >>> from zope.component import getUtility | ||
717 | 25 | 24 | ||
718 | 26 | >>> owner = factory.makePerson() | 25 | >>> owner = factory.makePerson() |
719 | 27 | >>> team_one = factory.makeTeam(owner=owner, name='staging-one') | 26 | >>> team_one = factory.makeTeam(owner=owner, name='staging-one') |
720 | @@ -127,7 +126,7 @@ | |||
721 | 127 | >>> from canonical.launchpad.interfaces import ( | 126 | >>> from canonical.launchpad.interfaces import ( |
722 | 128 | ... EmailAddressStatus, IEmailAddressSet, IPersonSet) | 127 | ... EmailAddressStatus, IEmailAddressSet, IPersonSet) |
723 | 129 | >>> from zope.component import getUtility | 128 | >>> from zope.component import getUtility |
725 | 130 | >>> login('foo.bar@canonical.com') | 129 | >>> login('admin@canonical.com') |
726 | 131 | >>> team = getUtility(IPersonSet).getByName('staging-two') | 130 | >>> team = getUtility(IPersonSet).getByName('staging-two') |
727 | 132 | >>> email = getUtility(IEmailAddressSet).new( | 131 | >>> email = getUtility(IEmailAddressSet).new( |
728 | 133 | ... 'contact@example.com', team, EmailAddressStatus.VALIDATED) | 132 | ... 'contact@example.com', team, EmailAddressStatus.VALIDATED) |
729 | 134 | 133 | ||
730 | === modified file 'lib/lp/services/mailman/doc/subscriptions.txt' | |||
731 | --- lib/lp/services/mailman/doc/subscriptions.txt 2009-06-03 16:03:04 +0000 | |||
732 | +++ lib/lp/services/mailman/doc/subscriptions.txt 2009-09-24 20:25:22 +0000 | |||
733 | @@ -1,4 +1,6 @@ | |||
735 | 1 | = Mailing list subscriptions = | 1 | ========================== |
736 | 2 | Mailing list subscriptions | ||
737 | 3 | ========================== | ||
738 | 2 | 4 | ||
739 | 3 | Both direct and indirect members of a team may subscribe to a team's mailing | 5 | Both direct and indirect members of a team may subscribe to a team's mailing |
740 | 4 | list. First, create the mailing list, which will send a notification messages | 6 | list. First, create the mailing list, which will send a notification messages |
741 | @@ -57,7 +59,7 @@ | |||
742 | 57 | >>> from lp.registry.interfaces.person import IPersonSet | 59 | >>> from lp.registry.interfaces.person import IPersonSet |
743 | 58 | >>> from zope.component import getUtility | 60 | >>> from zope.component import getUtility |
744 | 59 | 61 | ||
746 | 60 | >>> login('foo.bar@canonical.com') | 62 | >>> login('admin@canonical.com') |
747 | 61 | >>> person_set = getUtility(IPersonSet) | 63 | >>> person_set = getUtility(IPersonSet) |
748 | 62 | 64 | ||
749 | 63 | >>> anne = person_set.getByName('anne') | 65 | >>> anne = person_set.getByName('anne') |
750 | @@ -88,7 +90,7 @@ | |||
751 | 88 | 90 | ||
752 | 89 | Bart now leaves the team. His subscription is removed. | 91 | Bart now leaves the team. His subscription is removed. |
753 | 90 | 92 | ||
755 | 91 | >>> login('foo.bar@canonical.com') | 93 | >>> login('admin@canonical.com') |
756 | 92 | >>> bart = person_set.getByName('bart') | 94 | >>> bart = person_set.getByName('bart') |
757 | 93 | >>> team_one = person_set.getByName('itest-one') | 95 | >>> team_one = person_set.getByName('itest-one') |
758 | 94 | >>> bart.leave(team_one) | 96 | >>> bart.leave(team_one) |
759 | @@ -97,7 +99,8 @@ | |||
760 | 97 | >>> helpers.ensure_nonmembership('itest-one', bart) | 99 | >>> helpers.ensure_nonmembership('itest-one', bart) |
761 | 98 | 100 | ||
762 | 99 | 101 | ||
764 | 100 | == Alternative addresses == | 102 | Alternative addresses |
765 | 103 | ===================== | ||
766 | 101 | 104 | ||
767 | 102 | Now Anne decides to register another email address with Launchpad, however | 105 | Now Anne decides to register another email address with Launchpad, however |
768 | 103 | before she can validate this address, subscriptions for the list are | 106 | before she can validate this address, subscriptions for the list are |
769 | @@ -105,7 +108,7 @@ | |||
770 | 105 | the membership list, either as an enabled or disabled address. | 108 | the membership list, either as an enabled or disabled address. |
771 | 106 | 109 | ||
772 | 107 | >>> from canonical.launchpad.interfaces import IEmailAddressSet | 110 | >>> from canonical.launchpad.interfaces import IEmailAddressSet |
774 | 108 | >>> login('foo.bar@canonical.com') | 111 | >>> login('admin@canonical.com') |
775 | 109 | >>> email_set = getUtility(IEmailAddressSet) | 112 | >>> email_set = getUtility(IEmailAddressSet) |
776 | 110 | >>> email = email_set.new( | 113 | >>> email = email_set.new( |
777 | 111 | ... 'anne.x.person@example.net', anne, account=anne.account) | 114 | ... 'anne.x.person@example.net', anne, account=anne.account) |
778 | @@ -145,7 +148,8 @@ | |||
779 | 145 | No Privileges Person <no-priv@canonical.com> DISABLED | 148 | No Privileges Person <no-priv@canonical.com> DISABLED |
780 | 146 | 149 | ||
781 | 147 | 150 | ||
783 | 148 | == Case-preservation == | 151 | Case-preservation |
784 | 152 | ================= | ||
785 | 149 | 153 | ||
786 | 150 | Mailing lists preserve the case of the subscribed email address, | 154 | Mailing lists preserve the case of the subscribed email address, |
787 | 151 | although for subscription purposes, two email addresses that differs | 155 | although for subscription purposes, two email addresses that differs |
788 | @@ -154,7 +158,7 @@ | |||
789 | 154 | Emma joins Launchpad as normal, then subscribes a mixed-case alternative | 158 | Emma joins Launchpad as normal, then subscribes a mixed-case alternative |
790 | 155 | email address. | 159 | email address. |
791 | 156 | 160 | ||
793 | 157 | >>> login('foo.bar@canonical.com') | 161 | >>> login('admin@canonical.com') |
794 | 158 | >>> emma = factory.makePersonByName('Emma') | 162 | >>> emma = factory.makePersonByName('Emma') |
795 | 159 | >>> email = email_set.new( | 163 | >>> email = email_set.new( |
796 | 160 | ... 'EmmaXPerson@example.org', emma, account=emma.account) | 164 | ... 'EmmaXPerson@example.org', emma, account=emma.account) |
797 | 161 | 165 | ||
798 | === modified file 'lib/lp/services/mailman/testing/helpers.py' | |||
799 | --- lib/lp/services/mailman/testing/helpers.py 2009-06-25 04:06:00 +0000 | |||
800 | +++ lib/lp/services/mailman/testing/helpers.py 2009-09-24 20:25:22 +0000 | |||
801 | @@ -103,7 +103,7 @@ | |||
802 | 103 | 'Open Team'] | 103 | 'Open Team'] |
803 | 104 | browser.getControl('Create').click() | 104 | browser.getControl('Create').click() |
804 | 105 | # Create the mailing list. | 105 | # Create the mailing list. |
806 | 106 | browser.getLink('Configure mailing list').click() | 106 | browser.getLink('Create a mailing list').click() |
807 | 107 | browser.getControl('Apply for Mailing List').click() | 107 | browser.getControl('Apply for Mailing List').click() |
808 | 108 | mailing_list = review_list(team_name) | 108 | mailing_list = review_list(team_name) |
809 | 109 | # pylint: disable-msg=F0401 | 109 | # pylint: disable-msg=F0401 |
810 | 110 | 110 | ||
811 | === modified file 'lib/lp/services/mailman/testing/logwatcher.py' | |||
812 | --- lib/lp/services/mailman/testing/logwatcher.py 2009-07-17 00:26:05 +0000 | |||
813 | +++ lib/lp/services/mailman/testing/logwatcher.py 2009-09-24 20:25:22 +0000 | |||
814 | @@ -33,8 +33,8 @@ | |||
815 | 33 | 33 | ||
816 | 34 | BREAK_ON_TIMEOUT = bool(os.getenv('BREAK_ON_TIMEOUT')) | 34 | BREAK_ON_TIMEOUT = bool(os.getenv('BREAK_ON_TIMEOUT')) |
817 | 35 | LINES_TO_CAPTURE = 50 | 35 | LINES_TO_CAPTURE = 50 |
820 | 36 | LOG_GROWTH_WAIT_INTERVAL = datetime.timedelta(seconds=20) | 36 | LOG_GROWTH_WAIT_INTERVAL = datetime.timedelta(seconds=10) |
821 | 37 | FAILURE_CAPTURE_INTERVAL = datetime.timedelta(seconds=60) | 37 | FAILURE_CAPTURE_INTERVAL = datetime.timedelta(seconds=10) |
822 | 38 | SECONDS_TO_SNOOZE = 0.1 | 38 | SECONDS_TO_SNOOZE = 0.1 |
823 | 39 | Empty = object() | 39 | Empty = object() |
824 | 40 | NL = '\n' | 40 | NL = '\n' |
reviewer rockstar
= Summary =
Bug 435604 describes a critical problem we discovered while rolling out LP 3.0
on forster, the Mailman (and other) server. The problem is that with the move
to buildout for a lot of our packages, the sys.path that the Mailman binary
uses was not correct. The binary uses the system Python, not bin/py so none
of the buildout eggs were visible to it.
== Proposed fix ==
Extend the path hacking done in Mailman's mm_cfg.py to pick up the necessary
buildout eggs. Do this by importing _pythonpath.
== Pre-implementation notes ==
Discussion during cowboy rollout with gary, spm, and stub.
== Implementation details ==
Along the way, I updated all the MailmanLayer tests. These should all pass
now, with the usual caveat that these tests are flaky. That's why we don't
run them as part of our normal test suite.
== Tests ==
To test the specific critical fix in this branch, run:
% bin/test -vv --layer= MailmanLayer -t basic-integration
To see that all the tests have been updated for LP 3.0, run:
% bin/test -vv --layer= MailmanLayer
You may get spurious failures from the above. Your choices are to run each services/ mailman/ doc separately, or/and do 'make clean && make'
test in lib/lp/
between each run.
== Demo and Q/A ==
No demo or Q/A. Once we cherry pick this onto forster, if the mailing lists
work, we're gold.
= Launchpad lint =
Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.
Linting changed files: services/ mailman/ doc/logging. txt services/ mailman/ doc/subscriptio ns.txt /launchpad/ mailman/ monkeypatches/ __init_ _.py services/ mailman/ testing/ logwatcher. py services/ mailman/ doc/postings. txt services/ mailman/ doc/bounces. txt services/ mailman/ doc/basic- integration. txt services/ mailman/ doc/decorations .txt services/ mailman/ doc/messages. txt services/ mailman/ doc/recovery. txt services/ mailman/ doc/reactivate- lists.txt services/ mailman/ doc/create- lists.txt /launchpad/ mailman/ monkeypatches/ mm_cfg. py.in services/ mailman/ doc/contact- address. txt services/ mailman/ doc/staging. txt services/ mailman/ testing/ helpers. py services/ mailman/ doc/modify- lists.txt
lib/lp/
lib/lp/
lib/canonical
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/canonical
lib/lp/
lib/lp/
lib/lp/
lib/lp/
== Pyflakes Doctest notices ==
lib/lp/ services/ mailman/ doc/logging. txt
70: undefined name 'error_watcher'
71: undefined name 'error_watcher'
74: undefined name 'error_watcher'
75: undefined name 'error_watcher'
lib/lp/ services/ mailman/ doc/postings. txt
14: undefined name 'smtpd'
35: undefined name 'vette_watcher'
36: undefined name 'smtpd'
73: undefined name 'vette_watcher'
74: undefined name 'smtpd'
88: undefined name 'smtpd'
89: undefined name 'smtpd'
99: undefined name 'vette_watcher'
103: undefined name 'smtpd_watcher'
104: undefined name 'smtpd'
156: undefined name 'Browser'
168: undefined name 'smtpd_watcher'
169: undefined name 'smtpd'
212: undefined name 'vette_watcher'
213: undefined name 'smtpd'
244: undefined name 'smtpd'
259: undefine...