Merge lp://staging/~kfogel/launchpadlib/remove-lpscripts into lp://staging/launchpadlib
- remove-lpscripts
- Merge into trunk
Proposed by
Karl Fogel
Status: | Merged |
---|---|
Merge reported by: | Leonard Richardson |
Merged at revision: | not available |
Proposed branch: | lp://staging/~kfogel/launchpadlib/remove-lpscripts |
Merge into: | lp://staging/launchpadlib |
Diff against target: |
308 lines 1 file modified
contrib/lpscripts.py (+0/-304) |
To merge this branch: | bzr merge lp://staging/~kfogel/launchpadlib/remove-lpscripts |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Brad Crittenden (community) | code | Approve | |
Review via email: mp+14010@code.staging.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Karl Fogel (kfogel) wrote : | # |
Revision history for this message
Brad Crittenden (bac) wrote : | # |
Thanks for taking care of this Karl.
review:
Approve
(code)
Revision history for this message
Brad Crittenden (bac) : | # |
review:
Approve
(code)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === removed file 'contrib/lpscripts.py' |
2 | --- contrib/lpscripts.py 2009-09-29 15:39:26 +0000 |
3 | +++ contrib/lpscripts.py 1970-01-01 00:00:00 +0000 |
4 | @@ -1,304 +0,0 @@ |
5 | -#!/usr/bin/env python |
6 | - |
7 | -# Copyright (C) 2009 Canonical Ltd. |
8 | -# |
9 | -# This file is part of launchpadlib. |
10 | -# |
11 | -# launchpadlib is free software: you can redistribute it and/or modify it |
12 | -# under the terms of the GNU Lesser General Public License as published by the |
13 | -# Free Software Foundation, version 3 of the License. |
14 | -# |
15 | -# launchpadlib is distributed in the hope that it will be useful, but WITHOUT |
16 | -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
17 | -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License |
18 | -# for more details. |
19 | -# |
20 | -# You should have received a copy of the GNU Lesser General Public License |
21 | -# along with launchpadlib. If not, see <http://www.gnu.org/licenses/>. |
22 | - |
23 | -__metaclass__ = type |
24 | -__all__ = [ |
25 | - 'LaunchpadAPIScript', |
26 | - ] |
27 | - |
28 | - |
29 | -import os |
30 | -import sys |
31 | -from email.MIMEText import MIMEText |
32 | -from email.Utils import formataddr, formatdate |
33 | -import optparse |
34 | -import datetime |
35 | - |
36 | -from bzrlib.msgeditor import edit_commit_message |
37 | -from bzrlib.smtp_connection import SMTPConnection |
38 | -import bzrlib.config |
39 | - |
40 | -import _pythonpath |
41 | -import launchpadlib.errors |
42 | -from launchpadlib.launchpad import Launchpad |
43 | - |
44 | - |
45 | -class LaunchpadAPIScript: |
46 | - """Class for scripts that perform LP admin tasks via launchpadlib.""" |
47 | - REGISTRY_TEAM= u'registry' |
48 | - |
49 | - RTM_TEMPLATE = u"""\ |
50 | -Due: %(due)s |
51 | -Tags: %(tags)s |
52 | -URL: %(project_url)s |
53 | -List: %(list)s |
54 | ---- |
55 | -%(now)s |
56 | -%(message)s |
57 | -""" |
58 | - |
59 | - RTM_ADDRESS='launchpad+a7141e@rmilk.com' |
60 | - |
61 | - RTM_MESSAGE = u"" |
62 | - |
63 | - RTM_SUBJECT = "" |
64 | - |
65 | - USAGE="""\ |
66 | -%prog [options] [projects] |
67 | - |
68 | -'projects' is a list of project names or URLs to projects in |
69 | -Launchpad. This script does not do anything. Please extend the class |
70 | -LaunchpadAPIScript to do something useful. |
71 | -""" |
72 | - |
73 | - MSG_TEMPLATE = None |
74 | - SUBJECT = "" |
75 | - FEEDBACK = 'feedback@launchpad.net' |
76 | - COMMASPACE = ', ' |
77 | - NEWLINE = '\n' |
78 | - |
79 | - |
80 | - def message_data(self, proj, owner): |
81 | - """Construct a dictionary with data for interpolating messages.""" |
82 | - project_url = "https://launchpad.net/%s" % proj.name |
83 | - return dict( |
84 | - owner_name=owner.display_name, |
85 | - owner_display_name=owner.display_name, |
86 | - me=self.lp.me.display_name, |
87 | - project_url=project_url, |
88 | - project_name=proj.name, |
89 | - now=datetime.datetime.now(), |
90 | - today=datetime.date.today(), |
91 | - ) |
92 | - |
93 | - def send_email_message(self, msg_text, subject, to, sender, cc): |
94 | - """Actually send an email message.""" |
95 | - msg = MIMEText(msg_text.encode('utf-8'), 'plain', 'utf-8') |
96 | - |
97 | - msg['From'] = sender |
98 | - msg['Reply-To'] = self.FEEDBACK |
99 | - to_list = set() |
100 | - if self.opts.to_me: |
101 | - msg['To'] = sender |
102 | - to_list.add(sender) |
103 | - else: |
104 | - msg['To'] = to |
105 | - to_list.add(to) |
106 | - if cc is not None: |
107 | - msg['Cc'] = self.COMMASPACE.join(cc) |
108 | - to_list.update(cc) |
109 | - msg['Subject'] = subject |
110 | - msg['Date'] = formatdate() |
111 | - msg.epilogue = '' |
112 | - |
113 | - message = msg.as_string() |
114 | - |
115 | - if self.opts.dry_run: |
116 | - print message |
117 | - print "Message not sent" |
118 | - else: |
119 | - print "Sending..." |
120 | - SMTPConnection(bzrlib.config.GlobalConfig()).send_email(msg) |
121 | - print "email to: ", self.COMMASPACE.join(to_list) |
122 | - |
123 | - |
124 | - def send_email(self, project, owner): |
125 | - """Send the message to project owner, me, and list.""" |
126 | - sender = formataddr( |
127 | - (self.lp.me.display_name, |
128 | - self.lp.me.preferred_email_address.email)) |
129 | - to = formataddr( |
130 | - (owner.display_name, |
131 | - owner.preferred_email_address.email)) |
132 | - cc = [self.FEEDBACK, sender] |
133 | - message_data = self.message_data(project, owner) |
134 | - subject = self.SUBJECT % message_data |
135 | - text = self.MSG_TEMPLATE % message_data |
136 | - |
137 | - if not self.opts.rtm_only: |
138 | - if self.opts.edit_msg: |
139 | - infotext = ( |
140 | - "Edit your outgoing message. " |
141 | - "Everything above the line will be included.") |
142 | - separator = '-' * 27 + ' Do not remove this line ' + 27 * '-' |
143 | - try: |
144 | - text = edit_commit_message( |
145 | - infotext=infotext, |
146 | - ignoreline=separator, |
147 | - start_message=text) |
148 | - except (KeyboardInterrupt, SystemExit): |
149 | - raise |
150 | - self.send_email_message(text, subject, to, sender, cc) |
151 | - |
152 | - # Log a reminder in RTM via the email interface. |
153 | - # opts.rtm_address may be '' or None. |
154 | - if self.opts.rtm_address: |
155 | - to = self.opts.rtm_address |
156 | - subject = self.RTM_SUBJECT % self.message_data(project, owner) |
157 | - if self.opts.rtm_only: |
158 | - self.opts.rtm_tags += ' +user-not-contacted' |
159 | - message_data.update( |
160 | - dict( |
161 | - due=self.opts.due, |
162 | - tags=self.opts.rtm_tags, |
163 | - list=self.opts.rtm_list, |
164 | - message=self.rtm_message(project, owner) |
165 | - )) |
166 | - text = self.RTM_TEMPLATE % message_data |
167 | - self.send_email_message(text, subject, to, sender, None) |
168 | - |
169 | - def rtm_message(self, project, owner): |
170 | - return self.RTM_MESSAGE % self.message_data(project, owner) |
171 | - |
172 | - def whiteboard_message(self, proj, owner): |
173 | - return self.WHITEBOARD_MESSAGE % self.message_data(proj, owner) |
174 | - |
175 | - def update_whiteboard(self, proj, owner): |
176 | - """Make a note on the project whiteboard. |
177 | - |
178 | - Record the fact that the owner was notified and the date. |
179 | - """ |
180 | - if self.opts.to_me is True: |
181 | - return |
182 | - msg = self.whiteboard_message(proj, owner) |
183 | - if msg is None: |
184 | - return |
185 | - old_wb = proj.reviewer_whiteboard |
186 | - if old_wb: |
187 | - new_wb = self.NEWLINE.join((old_wb, msg)) |
188 | - else: |
189 | - new_wb = msg |
190 | - if self.opts.dry_run: |
191 | - print "New whiteboard would be:" |
192 | - print new_wb |
193 | - else: |
194 | - proj.reviewer_whiteboard = new_wb |
195 | - try: |
196 | - proj.lp_save() |
197 | - except launchpadlib.errors.HTTPError, e: |
198 | - print ("Unable to save new reviewer whiteboard. " |
199 | - "Please manually add the following:") |
200 | - print msg |
201 | - |
202 | - |
203 | - def addParserOptions(self): |
204 | - """Add arguments to the parser.""" |
205 | - self.parser.add_option( |
206 | - '-s', '--system', |
207 | - type='string', default='edge', dest='lpsystem', |
208 | - help="""\ |
209 | -The Launchpad system to use. Must be one of 'production', 'edge', |
210 | -'staging' or 'dev'.""") |
211 | - |
212 | - self.parser.add_option( |
213 | - '--dryrun', |
214 | - action='store_true', default=False, dest='dry_run', |
215 | - help="""If this option is used no email will be sent.""") |
216 | - |
217 | - self.parser.add_option( |
218 | - '--onlyme', |
219 | - action='store_true', default=False, dest='to_me', |
220 | - help="""\ |
221 | -If this option is used the email is only sent to yourself as a test.""") |
222 | - |
223 | - self.parser.add_option( |
224 | - '--rtm-only', |
225 | - action='store_true', default=False, dest='rtm_only', |
226 | - help="""\ |
227 | -Only set a reminder in RTM with the tag +user-not-contacted. |
228 | -Do not send email.""") |
229 | - |
230 | - self.parser.add_option( |
231 | - '--rtm', |
232 | - type='string', default=None, |
233 | - dest='rtm_address', |
234 | - help="""\ |
235 | -Provide your RememberTheMilk.com address for emailing tasks. It can be found under |
236 | -the 'Settings->Info' tab in RTM. The default is to use the Launchpad group account.""") |
237 | - |
238 | - self.parser.add_option( |
239 | - '--edit-msg', |
240 | - action='store_true', default=False, dest='edit_msg', |
241 | - help="""\ |
242 | -Open outgoing message in your EDITOR for customization.""") |
243 | - |
244 | - def parseArgs(self): |
245 | - """Parse the arguments. |
246 | - |
247 | - Sets self.opts and self.args. |
248 | - """ |
249 | - self.parser = optparse.OptionParser(self.USAGE, conflict_handler="resolve") |
250 | - |
251 | - self.addParserOptions() |
252 | - |
253 | - self.opts, self.args = self.parser.parse_args() |
254 | - if len(self.args) < 1: |
255 | - self.parser.error('Missing projects') |
256 | - |
257 | - def normalizeProjectName(self, project_name): |
258 | - """Project names may be passed as the full URL. Return just the name.""" |
259 | - project_name = project_name.strip() |
260 | - if project_name.endswith("/+review"): |
261 | - project_name = "/".join(project_name.split("/")[0:-1]) |
262 | - if (project_name.startswith("https://") or |
263 | - project_name.startswith("http://")): |
264 | - project_name = project_name.split("/")[-1] |
265 | - return project_name |
266 | - |
267 | - def process_project(self, project): |
268 | - """Process an individual project.""" |
269 | - pass |
270 | - |
271 | - def run(self): |
272 | - """Process the projects.""" |
273 | - print "Connecting..." |
274 | - sys.stdout.flush() |
275 | - try: |
276 | - self.lp = Launchpad.login_with(self.name, self.opts.lpsystem) |
277 | - except launchpadlib.errors.HTTPError, e: |
278 | - print "An error has occured contacting Launchpad." |
279 | - print e |
280 | - sys.exit(-1) |
281 | - print "done." |
282 | - |
283 | - for project_name in self.args: |
284 | - # For convenience, accept URLs as project names. |
285 | - project_name = self.normalizeProjectName(project_name) |
286 | - if not project_name: |
287 | - continue |
288 | - |
289 | - print "Examining project %s..." % (project_name,) |
290 | - try: |
291 | - proj = self.lp.projects[project_name] |
292 | - except KeyError: |
293 | - print "failed, because no project exists with that name." |
294 | - continue |
295 | - |
296 | - self.process_project(proj) |
297 | - |
298 | - def __init__(self, name=None): |
299 | - if name is None: |
300 | - name = os.path.split(sys.argv[0])[-1] |
301 | - self.name = name |
302 | - self.parseArgs() |
303 | - |
304 | - |
305 | -if __name__ == "__main__": |
306 | - script = LaunchpadAPIScript() |
307 | - sys.exit() |
308 | - script.run() |
...or should I just commit this?